Creating ANGULAR JS Custom Directives The coolest feature you’ve ever used. Let’s find out what it is!
Declarative & Model-Driven Behavior Imperativeness equals your problem. Declarative approach means colliding with somebody else’s problem. Also extending HTML. core concept #1
Modularity & Reusability across contexts Directives know their own element and local scope. We can pass additional data into directives as attributes, right on element. Write once, run anywhere! core concept #2
Keep it Local Sticks to a self-contained, modular scope, which understands its context: inside the directive, ‘element’ is like ‘this’. Uses messages, models to affect things elsewhere. Easier to maintain, easier to read, easier to scale. core concept #3
We know Angular Built-In Directives  ng-app  ng-bind  ng-model  ng-class  ng-controller  ng-show / ng-hide  ng-if  ng-switch Generally speaking, a directive is a function that’s attached to an element. But not JUST. It is a whole execution environment. Basic Angular JS directives you are usually using How are custom directives different from built-in? They are different only in naming conventions. Do not use ‘ng-’ in your custom directives.
Naming Custom Directives Angular uses a convention borrowed from other JS projects: names in HTML are hyphenated (snake case) while identifiers in the JS are camel-cased. Expect Angular to do this conversion automatically because of normalization process. Directive name in HTML and Normalization .directive(‘customDir’) function () { // Some code goes here }) <custom-dir></custom-dir> <span custom:dir></span> <span custom_dir></span> …
Let’s CREATE Custom Directive Directive is the heart of Angular JS Framework
Building Custom Directive Custom Directive Creating Process angular .module(‘moduleName’, [‘dep1’, ‘dep2’]) .directive(‘directiveName’) factoryFunction () { // Some code goes here })  .directive() is a method we call on an angular.module(), either at creation time or via reference, passing a name and a factory function  The factory will return either a function or an object containing a function and other settings When we talk about generic ‘factories’, we don’t mean $factory, which is an Angular implementation service. The factory pattern is all about Functional Programming: using basic JavaScript functions to build and return naiive objects or other functions.
What do we do with the factory function? There are two basic options  Returning only the link function  Link versus Compile  Pre-Link versus Post-Link How to choose? Link or configuration object? What is Pre-Link and Post-Link functions? All these relate to $compile service of Angular JS and recommended for high-skilled developers.  Return a configuration object  Return a ‘linking function But now IGNORE for today:
Using Config Object Today we need to remember that directive returns an object. We may use the list of properties. Remember, link property is optional. Returning object with directives’ configurations angular.module(‘moduleName’, []) .directive(‘customDir’) function () { return { link: function (scope, element, attrs) { element.bind(‘mouseenter’, function () { }); }, restrict: ‘ECMA’, template: ‘<div>Hello, World</div>’ }; });
Link Function Arguments Directives that want to modify the DOM typically use the link option to register DOM listeners as well as update the DOM.  scope - is an Angular scope object.  element - is the jqLite-wrapped element that this directive matches (declared on ‘this’).  attrs - object containing the HTML attributes defined on the element, including the directive invocating itself.  controller - is the directive's required controller instance(s) or it's own controller (optional).  transcludeFn is a transclude linking function pre-bound to the correct transclusion scope (optional). Creating a Directive that Manipulates the DOM angular.module(‘moduleName’, []) .directive(‘customDir’) function () { return { link: function (scope, element, attrs) { element.bind(‘mouseenter’, function () { }); }, restrict: ‘ECMA’, template: ‘<div>Hello, World</div>’ }; });
Link Function Arguments $scope is assignable, but should be reserved for angular functions to pass into a controller, other context. It is a shorthand, by which we’re calling the $scopeProvider, which is Dependency-Injecting the scope for us. scope is just our own, customizable reference for directive’s local scope. $scope VERSUS scopeangular.module(‘moduleName’, []) .directive(‘customDir’) function () { return { link: function (scope, element, attrs) { element.bind(‘mouseenter’, function () { }); }, restrict: ‘ECMA’, template: ‘<div>Hello, World</div>’ }; });
Using jqLite Angular will defer to jQuery, if present, but provides its own subset of jQuery for basic DOM tasks. You can not just use ‘$( )’, nor find using selectors, unfortunately. But all built-in ‘element’ refs are already pre- wrapped in jqLite object. Try to chain methods as you normally would. You can use Angular jqLite for basic DOM tasks  addClass()  after()  append()  attr()  bind()  children()  clone()  contents()  css()  data()  eq()  find()  hasClass()  html()  nest()  on()  off()  parent()  prepend()  prop()  ready()  remove()  removeAttr()  removeClass()  removeData()  replaceWith()  text()  toggleClass()  triggerHandler()  unbind()  val()  wrap()
Using jqLite $(‘selector’).bind(‘mouseenter’, function () {}); The same as.. angular.module(‘moduleName’, []) .directive(‘customDir’) function () { return { link: function (scope, element, attrs) { element.bind(‘mouseenter’, function () { do some stuff.. }); }, restrict: ‘ECMA’, template: ‘<div>Hello, World</div>’ }; }); Let’s review another ‘modern’ directives’ options…
Templating in Directive template – property where we can store our template as a string. templateUrl – this property allows us to load template from a file, using path. Use the template you need angular.module(‘moduleName’, []) .directive(‘customDir’) function () { return { link: function (scope, element, attrs) { element.bind(‘mouseenter’, function () { }); }, restrict: ‘ECMA’, template: ‘<div>Hello, World</div>’, // or templateUrl: ‘path/dir/template.html’ }; });
Restrict Property Remember that directives are re-usable. We can restrict the usage of a directive to (a) specific context(s). Defaults to ‘A’. Stack as a single string ‘EACM’.  ‘E’lement,  ‘A’ttribute,  ‘C’lass,  co’M’ment. Memorize like ECMAScript <custom></custom> <span custom=“somevalue”></span> <span class=“custom_dir”></span> <!– directive: custom somevalue --> angular.module(‘moduleName’, []) .directive(‘customDir’) function () { return { restrict: ‘ECMA’, }; });
Replace Property [DEPRECATED] By default, a directive element will wrap the contents of a template. The ‘element’ object will be the outer directive element. To instead replace the directive element (and object) with the contents of the template, use replace: true This is especially critical when declaring as an element. Wrap without showing directive element angular.module(‘moduleName’, []) .directive(‘customDir’) function () { return { replace: true, template: ‘<header>Some info</header>’ }; }); <body> <custom-dir> <header> Some info </header> </custom-dir> </body>
Directive Isolate Scope We have the option, in directives, of using either: the local $scope (from our own controller, possibly) and a new, per-instance, ‘isolate scope’. Isolate scopes still have a parent $scope, but they’re ‘eccapsulated’ or, in other words, detached from the inheritance chain. This is especially useful with repeats, so variables can be fully local to the instance Using isolate scope in a custom directive .directive(‘customDir’) function () { return { scope: true, // creates child scope template: ‘<div>Hello, World</div>’ }; }); .directive(‘customDir’) function () { return { scope: { dataSet: ‘@’, }, // creates isolated scope template: ‘<div>Hello, World</div>’ }; });
Isolate Scope Data-Binding Angular provides us with ways to bind the value of properties in isolate scope to attributes on the element, using special operators. By default, an operator alone will be assumed to refer to a same- named attr. ‘@’ - binds the local scope property to primitive value of the DOM attribute. Result is always a string because attributes are strings. ‘=‘ - binds the local scope property to a parent scope property having same name as the value of the DOM attribute. ‘&’ - binds local scope property to the output of an expression defined in the DOM attribute. It’s like a function wrapper. Ways to bind values of properties .directive(‘customDir’) function () { return { scope: { job: ‘@job’, // or only ‘@’ }, template: ‘<div>Hello, World</div>’ }; }); <custom job=“dev”></custom> scope: { job: ‘@’, } // the same as scope.job = attrs.job;
You also NEED TO KNOW Something MORE You should re-view some information about custom directives by yourself
Try to find…  Transclude  Controller  controllerAs  Require …more about such properties You will need this information in the future to create more complex custom directives, using them as the LEGO blocks.
References …Learn more Angular Directives from Scratch Creating Custom Directives Comprehensive Directive API
Thank You! This presentation was created specially for if058.Web-UI Group. Yaroslav Prodanchuk prepared by:

Custom AngularJS Directives

  • 1.
    Creating ANGULAR JS Custom Directives Thecoolest feature you’ve ever used. Let’s find out what it is!
  • 2.
    Declarative & Model-Driven Behavior Imperativeness equalsyour problem. Declarative approach means colliding with somebody else’s problem. Also extending HTML. core concept #1
  • 3.
    Modularity & Reusability across contexts Directivesknow their own element and local scope. We can pass additional data into directives as attributes, right on element. Write once, run anywhere! core concept #2
  • 4.
    Keep it Local Sticksto a self-contained, modular scope, which understands its context: inside the directive, ‘element’ is like ‘this’. Uses messages, models to affect things elsewhere. Easier to maintain, easier to read, easier to scale. core concept #3
  • 5.
    We know AngularBuilt-In Directives  ng-app  ng-bind  ng-model  ng-class  ng-controller  ng-show / ng-hide  ng-if  ng-switch Generally speaking, a directive is a function that’s attached to an element. But not JUST. It is a whole execution environment. Basic Angular JS directives you are usually using How are custom directives different from built-in? They are different only in naming conventions. Do not use ‘ng-’ in your custom directives.
  • 6.
    Naming Custom Directives Angularuses a convention borrowed from other JS projects: names in HTML are hyphenated (snake case) while identifiers in the JS are camel-cased. Expect Angular to do this conversion automatically because of normalization process. Directive name in HTML and Normalization .directive(‘customDir’) function () { // Some code goes here }) <custom-dir></custom-dir> <span custom:dir></span> <span custom_dir></span> …
  • 7.
    Let’s CREATE Custom Directive Directive isthe heart of Angular JS Framework
  • 8.
    Building Custom Directive CustomDirective Creating Process angular .module(‘moduleName’, [‘dep1’, ‘dep2’]) .directive(‘directiveName’) factoryFunction () { // Some code goes here })  .directive() is a method we call on an angular.module(), either at creation time or via reference, passing a name and a factory function  The factory will return either a function or an object containing a function and other settings When we talk about generic ‘factories’, we don’t mean $factory, which is an Angular implementation service. The factory pattern is all about Functional Programming: using basic JavaScript functions to build and return naiive objects or other functions.
  • 9.
    What do wedo with the factory function? There are two basic options  Returning only the link function  Link versus Compile  Pre-Link versus Post-Link How to choose? Link or configuration object? What is Pre-Link and Post-Link functions? All these relate to $compile service of Angular JS and recommended for high-skilled developers.  Return a configuration object  Return a ‘linking function But now IGNORE for today:
  • 10.
    Using Config Object Todaywe need to remember that directive returns an object. We may use the list of properties. Remember, link property is optional. Returning object with directives’ configurations angular.module(‘moduleName’, []) .directive(‘customDir’) function () { return { link: function (scope, element, attrs) { element.bind(‘mouseenter’, function () { }); }, restrict: ‘ECMA’, template: ‘<div>Hello, World</div>’ }; });
  • 11.
    Link Function Arguments Directivesthat want to modify the DOM typically use the link option to register DOM listeners as well as update the DOM.  scope - is an Angular scope object.  element - is the jqLite-wrapped element that this directive matches (declared on ‘this’).  attrs - object containing the HTML attributes defined on the element, including the directive invocating itself.  controller - is the directive's required controller instance(s) or it's own controller (optional).  transcludeFn is a transclude linking function pre-bound to the correct transclusion scope (optional). Creating a Directive that Manipulates the DOM angular.module(‘moduleName’, []) .directive(‘customDir’) function () { return { link: function (scope, element, attrs) { element.bind(‘mouseenter’, function () { }); }, restrict: ‘ECMA’, template: ‘<div>Hello, World</div>’ }; });
  • 12.
    Link Function Arguments $scopeis assignable, but should be reserved for angular functions to pass into a controller, other context. It is a shorthand, by which we’re calling the $scopeProvider, which is Dependency-Injecting the scope for us. scope is just our own, customizable reference for directive’s local scope. $scope VERSUS scopeangular.module(‘moduleName’, []) .directive(‘customDir’) function () { return { link: function (scope, element, attrs) { element.bind(‘mouseenter’, function () { }); }, restrict: ‘ECMA’, template: ‘<div>Hello, World</div>’ }; });
  • 13.
    Using jqLite Angular willdefer to jQuery, if present, but provides its own subset of jQuery for basic DOM tasks. You can not just use ‘$( )’, nor find using selectors, unfortunately. But all built-in ‘element’ refs are already pre- wrapped in jqLite object. Try to chain methods as you normally would. You can use Angular jqLite for basic DOM tasks  addClass()  after()  append()  attr()  bind()  children()  clone()  contents()  css()  data()  eq()  find()  hasClass()  html()  nest()  on()  off()  parent()  prepend()  prop()  ready()  remove()  removeAttr()  removeClass()  removeData()  replaceWith()  text()  toggleClass()  triggerHandler()  unbind()  val()  wrap()
  • 14.
    Using jqLite $(‘selector’).bind(‘mouseenter’, function() {}); The same as.. angular.module(‘moduleName’, []) .directive(‘customDir’) function () { return { link: function (scope, element, attrs) { element.bind(‘mouseenter’, function () { do some stuff.. }); }, restrict: ‘ECMA’, template: ‘<div>Hello, World</div>’ }; }); Let’s review another ‘modern’ directives’ options…
  • 15.
    Templating in Directive template– property where we can store our template as a string. templateUrl – this property allows us to load template from a file, using path. Use the template you need angular.module(‘moduleName’, []) .directive(‘customDir’) function () { return { link: function (scope, element, attrs) { element.bind(‘mouseenter’, function () { }); }, restrict: ‘ECMA’, template: ‘<div>Hello, World</div>’, // or templateUrl: ‘path/dir/template.html’ }; });
  • 16.
    Restrict Property Remember thatdirectives are re-usable. We can restrict the usage of a directive to (a) specific context(s). Defaults to ‘A’. Stack as a single string ‘EACM’.  ‘E’lement,  ‘A’ttribute,  ‘C’lass,  co’M’ment. Memorize like ECMAScript <custom></custom> <span custom=“somevalue”></span> <span class=“custom_dir”></span> <!– directive: custom somevalue --> angular.module(‘moduleName’, []) .directive(‘customDir’) function () { return { restrict: ‘ECMA’, }; });
  • 17.
    Replace Property [DEPRECATED] Bydefault, a directive element will wrap the contents of a template. The ‘element’ object will be the outer directive element. To instead replace the directive element (and object) with the contents of the template, use replace: true This is especially critical when declaring as an element. Wrap without showing directive element angular.module(‘moduleName’, []) .directive(‘customDir’) function () { return { replace: true, template: ‘<header>Some info</header>’ }; }); <body> <custom-dir> <header> Some info </header> </custom-dir> </body>
  • 18.
    Directive Isolate Scope Wehave the option, in directives, of using either: the local $scope (from our own controller, possibly) and a new, per-instance, ‘isolate scope’. Isolate scopes still have a parent $scope, but they’re ‘eccapsulated’ or, in other words, detached from the inheritance chain. This is especially useful with repeats, so variables can be fully local to the instance Using isolate scope in a custom directive .directive(‘customDir’) function () { return { scope: true, // creates child scope template: ‘<div>Hello, World</div>’ }; }); .directive(‘customDir’) function () { return { scope: { dataSet: ‘@’, }, // creates isolated scope template: ‘<div>Hello, World</div>’ }; });
  • 19.
    Isolate Scope Data-Binding Angularprovides us with ways to bind the value of properties in isolate scope to attributes on the element, using special operators. By default, an operator alone will be assumed to refer to a same- named attr. ‘@’ - binds the local scope property to primitive value of the DOM attribute. Result is always a string because attributes are strings. ‘=‘ - binds the local scope property to a parent scope property having same name as the value of the DOM attribute. ‘&’ - binds local scope property to the output of an expression defined in the DOM attribute. It’s like a function wrapper. Ways to bind values of properties .directive(‘customDir’) function () { return { scope: { job: ‘@job’, // or only ‘@’ }, template: ‘<div>Hello, World</div>’ }; }); <custom job=“dev”></custom> scope: { job: ‘@’, } // the same as scope.job = attrs.job;
  • 20.
    You also NEED TOKNOW Something MORE You should re-view some information about custom directives by yourself
  • 21.
    Try to find… Transclude  Controller  controllerAs  Require …more about such properties You will need this information in the future to create more complex custom directives, using them as the LEGO blocks.
  • 22.
    References …Learn more Angular Directivesfrom Scratch Creating Custom Directives Comprehensive Directive API
  • 23.
    Thank You! This presentationwas created specially for if058.Web-UI Group. Yaroslav Prodanchuk prepared by: