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', ['$', '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:

Hello





 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)  attributes (A)  class names ()  comments (M)

7 Directives var myModule = angular.module(...); myModule.directive('directiveName', function factory(injectables) { var directiveDefinitionObject = { priority: 0, template: '

', // or // function(tElement, tAttrs) { ... }, // or templateUrl: 'directive.', // 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 it

18 A few words on transclusion

 Rememebr the memory leak from closures: ctrl.expand = function() { $transclude(function(transEl) { content.append(transEl); }); ctrl.expanded = true; };

ctrl.collapse = function() { content.empty(); // content empty – transcluded scope still there ctrl.expanded = false; };

19 A few words on transclusion

 There is a fix: var content = $element.find('.content'); var transcludedScope; ctrl.expand = function() { $transclude(function(transEl, transScope) { content.append(transEl); transcludedScope = transScope; }); ctrl.expanded = true; }; ctrl.collapse = function() { transcludedScope.$destroy(); transcludedScope = null; content.empty(); ctrl.expanded = false; };

20 Components

 Components are meant to control their own view and data

 Components only use an isolate scope and are unable to modify DOM outside their scope

 Components are meant to modify only own scoped data, even if they allow for two way bindings bindings: { value: '<', // one way binding, changes in child do not reflect in parent scope comment: '@‘, // value binding onUpdate: ‘&’, // callback onComplete: ‘&’ // callback }

 In order to change data it should call the correct event (through a callback function) and the changed data as a parameter

21 Ideally, the whole application should be a tree of components that implement clearly defined inputs and outputs, and minimize two-way data binding. That way, it's easier to predict when data changes and what the state of a component is.

 Components can require the controller of other components in order to communicate with it’s parents without using events

22 Services

module.service('MyService', function() { this.method1 = function() { //..method1 logic } this.method2 = function() { //..method2 logic } });

 Services are singleton (all elements get a references to the same instance of service)

 Only initialized when they are required (Lazy Initialization)

 It is created with the key word new

 Reference can be used to access data; scope is defined by ‘this’ key word

23 Factories

module.factory('MyFactory', function() { var factory = {}; factory.method1 = function() { //..method1 logic } factory.method2 = function() { //..method2 logic }

return factory; });

 It always return a new instance of the object

 When injected, it will return a instance that can be used but not shared between angular elements

24 Decorators

.config([ '$provide', function($provide) {

$provide.decorator('myService', [ '$delegate', function myServiceDecorator($delegate) {

function helperFn() { // an additional fn to add to the service }

$delegate.aHelpfulAddition = helperFn; return $delegate; } ]);

25 Decorators

The $delegate is a service you want to decorate

The purpose is to enrich or replace the behavior of the $delegate service

Decorators can also be declare as module decorators, but they are executed after the provider decorators

26 THANK YOU!

Vlad Costel Ungureanu [email protected]

This is a free course from LearnStuff.io – not for commercial use –