Angularjs Elements by Vlad Costel Ungureanu for “Learn Stuff” and “CGM Romania” Dependency Injection
Total Page:16
File Type:pdf, Size:1020Kb
AngularJS Elements by Vlad Costel Ungureanu for “Learn Stuff” and “CGM Romania” Dependency Injection Inversion of Control $injector is responsible for creating and managing dependencies Services, factories, filters and animations are created by factory methods: angular.module('myModule', []) .factory('serviceId', ['depService', function(depService) { // ... }]) .directive('directiveName', ['depService', function(depService) { // ... }]) .filter('filterName', ['depService', function(depService) { // ... }]); 2 Dependency Injection Controllers are created by constructor functions: someModule.controller('MyController', ['$scope', 'dep1', 'dep2', function($scope, dep1, dep2) { // ... $scope.aMethod = function() { // ... } // ... }]); Dependencies can also be implicit if name of component matches the name of the variable Dependencies can also be injected in a module by using run and config functions: angular.module('myModule', []) .config(['depProvider', function(depProvider) { // ... }]) .run(['depService', function(depService) { // ... }]); 3 Dependency Injection Dependency injection using $Inject: var MyController = function($scope, reference) { // ... } MyController.$inject = ['$scope', ‘name_for_the_reference']; someModule.controller('MyController', MyController); $injector is a service locator (design pattern) It creates controllers and their dependencies as they are found in the document 4 Name Normalization The following example illustrates the may ways that name normalizations works in Angular: <div ng-controller="Controller"> Hello <input ng-model='name'> <hr/> <span ng-bind="name"></span> <br/> <span ng:bind="name"></span> <br/> <span ng_bind="name"></span> <br/> <span data-ng-bind="name"></span> <br/> <span x-ng-bind="name"></span> <br/> </div> Normalisation rules: Strip x- and data- from the front of the element/attributes. Convert the :, -, or _-delimited name to camelCase. 5 Useful directives ng-app: initialize angular apps ng-init: initalize app data ng-model: binds HTML input to app data ng-show: shows or hides an HTML element ng-disabled: sets disabled attribute on an HTML element ng-class: binds app data to class property of HTML element ng-selected: sets selected attribute if provided expression evaluates to true ng-checked: sets checked attribute if provided expression evaluates to true ng-bind: replace HTML element text with expression value# ng-if: removes or recreates a portion of the DOM tree (works by cloning elements) ng-repeat: clones HTML elements for items in a collection ng-[any_DHTML_event]: specify custom behavior on specified event ng-pattern: adds pattern validation ng-maxlength: adds max length character validation ng-required: adds required valdiation 6 Directives $compile can match directives based on: element names (E) <my-dir></my-dir> attributes (A) <span my-dir="exp"></span> class names (C) <span class="my-dir: exp;"></span> comments (M) <!-- directive: my-dir exp --> 7 Directives var myModule = angular.module(...); myModule.directive('directiveName', function factory(injectables) { var directiveDefinitionObject = { priority: 0, template: '<div></div>', // or // function(tElement, tAttrs) { ... }, // or templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... }, transclude: false, restrict: 'A', templateNamespace: 'html', scope: false, controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... }, controllerAs: 'stringIdentifier', bindToController: false, 8 Directives require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'], multiElement: false, compile: function compile(tElement, tAttrs, transclude) { return { pre: function preLink(scope, iElement, iAttrs, controller) { ... }, post: function postLink(scope, iElement, iAttrs, controller) { ... } } // or // return function postLink( ... ) { ... } }, // or // link: { // pre: function preLink(scope, iElement, iAttrs, controller) { ... }, // post: function postLink(scope, iElement, iAttrs, controller) { ... } // } }; return directiveDefinitionObject; }); 9 Directives priority: if there are multiple directive defined for the same DOM element, indicates the order template: string or function returning the HTML template of the directive templateURL: the ULR where the HTML template is stored transclude: extract elements where the directive appears, compile them and make them available for the directive restrict: restrict to the type or type the directive tag can be used scope: false will not create a new scope and the parent scope will be used true will create new child scope for directive in scope we can add variables and their bindings this variables become the directive attributes keep in mind that only one scope can be created for a single DOM element (two directives on the same element will share the scope) {} will create an isolate scope (there can be only one for DOM elements) 10 Directives controller: $scope - current scope associated with the element $element - current element $attrs - current attributes object for the element $transclude - A transclude linking function pre-bound to the correct transclusion scope: function([scope], cloneLinkingFn, futureParentElement, slotName): scope: (optional) override the scope. controllerAs: the name of the controller scope to be used in the directive and the directives template bindToController: if true after controller is instantiated, variables will be bound to the controller scope, which means that there is no need to inject $scope bindTocontroller also allows binding of variables instead of declaring them in scope attribute. 11 Directives require: require and inject another directive into the current directvie string containing the name of the directive to pass to the linking function an array containing the names of directives to pass to the linking function( controller of directives will be passed) an object whose values are directives to pass to the linking function. The argument passed to the linking function will also be an object with matching keys, whose values will hold the corresponding controllers. Require naming conventions: no prefix - Locate the required controller on the current element. ? - Attempt to locate the required controller ^ - Locate the required controller by searching the element and its parents ^^ - Locate the required controller by searching the element's parents ?^ - Attempt to locate the required controller by searching the element and its parents ?^^ - Attempt to locate the required controller by searching the element's parents 12 Directives multipleElement: if true, collects DOM nodes, between directive start and end tags, as directive elements compile: compile the DOM of the directive link: link the listeners the DOM elements Link function parameters: scope : The scope of the directive elem : Dom element where the directive is applied attr : Collection of attributes of the Dom Element ctrl : Array of controllers required by the directive preLink: executed before linking; should not change DOM postLink: executed after linking 13 Directives Lifecycle hooks $onInit() – after binding bot before pre & post linking functions for the directives on this element and should contain initialisation code $onChanges(changesObj) - Called whenever one-way (<) or interpolation (@) bindings are updated. ChangesObj contains as keys the name of the bindings and the value as { currentValue, previousValue, isFirstChange() } $doCheck() - Called on each turn of the digest cycle. Provides an opportunity to detect and act on changes. $onDestroy() - Called on a controller when its containing scope is destroyed. Use this hook for releasing external resources, watches and event handlers. $postLink() - Called after this controller's element and its children have been linked. Similar to the post-link function this hook can be used to set up DOM event handlers and do direct DOM manipulation. 14 Directives vs Components Directive Component a bindings No Yes (binds to controller) bindToController Yes (default: false) No (use bindings instead) compile function Yes No controller Yes Yes (default function() {}) controllerAs Yes (default: false) Yes (default: $ctrl) link functions Yes No multiElement Yes No priority Yes No replace Yes (deprecated) No require Yes Yes restrict Yes No (restricted to elements only) scope Yes (default: false) No (scope is always isolate) template Yes Yes, injectable templateNamespace Yes No templateUrl Yes Yes, injectable terminal Yes No transclude Yes (default: false) Yes (default: false) 15 A few words on transclusion app.directive('myCard', function() { return { scope: { title: '=myTitle', pic: '=myPic' }, templateUrl: 'myCard', transclude: true, link: function(scope, el, attrs, ctrl, transclude) { el.find('.content').append(transclude()); } }; }); 16 A few words on transclusion 17 A few words on transclusion Transclusion helps to introduce html elements in the page without the use of Jquery since there is a directive that indicates where to insert the HTML If you insert data bindings in a transclude HTML block the binding will inherit the value from out scope of the directive While having access to the out scope, it’s the reference to the transclusion scope is held by the scope that calls the transclusion When the parent gets destroyed the transclusion scope will also be destroyed Element transclusion implies that an element and all his descendants form a transcluded scope Personal opinion: stay away from it if you don’t need