Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

37
Building Custom AngularJS Direc6ves Dan Wahlin

description

AngularJS provides many built-in directives that can be used to manipulate the DOM, handle events, and more but there will be times when you need to write custom directives. How do you get started? Are directives really as scary as they look at first glance? In this session Dan Wahlin will provide a step-by-step look at creating custom AngularJS directives and show how to use templates, controllers, the link function, and many other features. You'll also see how custom directives can be used along with other AngularJS features such as $http interceptors and validation. By the end of the session you'll realize that directives aren't quite as scary as they first appear.

Transcript of Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Page 1: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Building  Custom  AngularJS  Direc6ves

Dan  Wahlin  

Page 2: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Dan  Wahlin  

Blog h;p://weblogs.asp.net/dwahlin Twi;er

@DanWahlin  

Page 3: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

D  

Page 4: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

1  

Page 5: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

@ =  &  

Page 6: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Transclusion  

Page 7: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Agenda •  The  Role  of  Direc6ves  •  Peeking  Under  the  Hood  •  Shared  vs.  Isolate  Scope  •  Linking  to  the  DOM  •  Controller  Love  •  Direc6ve  Examples  

Page 8: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Key  AngularJS  Direc6ves

Applica'on    

•  ng-­‐app  •  ng-­‐controller  

Forms    

•  ng-­‐maxlength  •  ng-­‐minlength  •  ng-­‐paKern  •  ng-­‐required  •  ng-­‐submit  

Templates    

•  ng-­‐disabled  •  ng-­‐cloak  •  ng-­‐hide  •  ng-­‐if  •  ng-­‐repeat  •  ng-­‐show  •  ng-­‐switch  •  ng-­‐view  

Data  Binding    

•  ng-­‐bind  •  ng-­‐href  •  ng-­‐init  •  ng-­‐model  •  ng-­‐src  •  ng-­‐style  

Behavior    

•  ng-­‐blur  •  ng-­‐change  •  ng-­‐checked  •  ng-­‐click  •  ng-­‐key*  •  ng-­‐mouse*  

Page 9: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Using  AngularJS  Direc6ves •  AKribute  direc6ves  

                 <span  my-­‐dir="exp"></span>  

 •  Element  direc6ves    

     <my-­‐dir></my-­‐dir>  

   

 

•  CSS  class  direc6ves  

       <span  class="my-­‐dir:  exp;"></span>  

 •  Comment  direc6ves  

         <!-­‐-­‐  directive:  my-­‐dir  exp  -­‐-­‐>  

   

 

Page 10: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Custom  Direc6ves

Data-­‐Driven  Direc'ves    

All  about  data,  using  other  direc'ves  and  a  controller  

 

DOM-­‐Driven  Direc'ves    

All  about  DOM  Manipula'on  

 

Page 11: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Agenda •  The  Role  of  Direc6ves  •  Peeking  Under  the  Hood  •  Shared  vs.  Isolate  Scope  •  Linking  to  the  DOM  •  Controller  Love  •  Direc6ve  Examples  

Page 12: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

templateUrl  

scope  

restrict   template  

controller   link  

Page 13: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

angular.module('moduleName')  

       .directive('myDirective',  function  ()  {  

       return  {  

               restrict:  'EA',  //E  =  element,  A  =  attribute,  C  =  class,  M  =  comment      

               scope:  {  

                       //@  reads  the  attribute  string  value,                            //=  provides  two-­‐way  binding,                            //&  works  with  functions  

                       title:  '@'                    },  

               template:  '<div>{{  myVal  }}</div>',  

               templateUrl:  'mytemplate.html',  

               controller:  controller,  

               link:  function  ($scope,  element,  attrs)  {  }  //DOM  manipulation  

       }  

});  

hKp://docs.angularjs.org/api/ng/service/$compile  

Page 14: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Agenda •  The  Role  of  Direc6ves  •  Peeking  Under  the  Hood  •  Shared  vs.  Isolate  Scope  •  Linking  to  the  DOM  •  Controller  Love  •  Direc6ve  Examples  

Page 15: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Shared Scope

Parent  Scope  

Child  Scope  

Page 16: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Isolate Scope

Page 17: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Parent  Scope  

Child  Scope  

Wall  Blocks  Parent  Scope  

Page 18: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

   

Controller    

$scope.customers=[];                    

Depends  on  parent  scope  

 $scope.customers=[];  

   

Direc've  

Shared  

   

Controller    

$scope.customers=[];                    

Isolated  from  parent  scope  

 $scope.customers=[];  $scope.isolated  =  true;  

 Direc've  

Not  Shared  

Shared  Scope   Isolate  Scope  

Page 19: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

hKp://codepen.io/danwahlin  

Page 20: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Shared  Scope  Direc6ve  Example var  app  =  angular.module('myModule',  []);    app.controller('Controller',  ['$scope',  function  ($scope)  {          $scope.customer  =  {                  name:  'David',                  street:  '1234  Anywhere  St.'          };  }]);    app.directive('sharedScope',  function  ()  {          return  {                  template:  'Name:  {{customer.name}}  Street:  {{customer.street}}'          };  });  

Scope  is  inherited  

<div  shared-­‐scope></div>  

Page 21: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Isola6ng  Scope  in  Direc6ves angular.module('myModule')          .directive('isolateScope',  function  ()  {                  return  {                          scope:  {},  //isolate  scope                            template:  'Name:  {{customer.name}}  Street:  '  +                                                '{{customer.street}}'                  };          });  

<div  isolate-­‐scope></div>  No  data  will  display!  

Page 22: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Hi,  I'm  Dan  

String  with  one-­‐way  binding  

@  

   

$scope.first='James';                  

Direc6ve  can  access  a  string  value  

 scope:  {  name:  '@'  }  

 Direc've  

@  isolate  scope  property  

<my-­‐directive  name="{{first}}"  />  

Page 23: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Hi,  I'm  Dan  

No,  you're  Jim  

Bi-­‐direc6onal  Binding  

=  

   

$scope.person={name:'Dan'};                  

Two-­‐way  binding  created  

 scope:  {  customer:  '='  }  

 Direc've  

=  isolate  scope  property  

<my-­‐directive  customer="person"  />  

Page 24: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Call  me  back  at:  123-­‐1234  

Calling  123-­‐1234  

Func6on  Callback  

&  

   

$scope.click=func6on()  {  };                  

Can  invoke  external  func6on  

 scope:  {  ac6on:  '&'  }  

 Direc've  

&  isolate  scope  property  

<my-­‐directive  action="click()"  />  

Page 25: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

@  Bind  a  local  scope  property  to  the  value  of  a  DOM  aKribute.  The  result  

is  always  a  string.    

scope:  {  name:  '@'  }  à  <my-­‐directive  name="{{name}}"  />    

=  Creates  a  bi-­‐direc6onal  binding  between  a  local  scope  property  and  the  parent  scope  property.  

     scope:  {  customer:  '='  }  à  <my-­‐directive  customer="person"  />  

&  Execute  an  expression/func6on  in  the  context  of  the  parent  scope.          scope:  {  click:  '&'  }  à  <my-­‐directive  click="click()"  />  

Page 26: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Agenda •  The  Role  of  Direc6ves  •  Peeking  Under  the  Hood  •  Shared  vs.  Isolate  Scope  •  Linking  to  the  DOM  •  Controller  Love  •  Examples  

Page 27: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

angular.module('directivesModule')          .directive('domDirective',  function  ()  {          return  {                  restrict:  'A',                  link:  function  ($scope,  element,  attrs)  {                          element.bind('click',  function  ()  {                                  element.html('You  clicked  me!');                          });                          element.bind('mouseenter',  function  ()  {                                  element.css('background-­‐color',  'yellow');                          });                          element.bind('mouseleave',  function  ()  {                                  element.css('background-­‐color',  'white');                          });                  }          };  });  

<div  dom-­‐directive>Click  Me!</div>  

Page 28: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Agenda •  The  Role  of  Direc6ves  •  Peeking  Under  the  Hood  •  Shared  vs.  Isolate  Scope  •  Linking  to  the  DOM  •  Controller  Love  •  Direc6ve  Examples  

Page 29: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

 angular.module('directivesModule')      .directive('isolateScopeWithController',  function  ()  {                  return  {                          restrict:  'EA',                          scope:  {datasource:  '=',  add:  '&'},                          controller:  function  ($scope)  {                                  function  init()  {                                          $scope.customers  =  angular.copy($scope.datasource);                                  }                                  init();                                  $scope.addCustomer  =  function  ()  {                                          //Call  external  scope's  function                                          $scope.add();                                          //Add  new  customer  to  directive  scope                                          $scope.customers.push({  …  });                                  };                          },                          template:  '<button  ng-­‐click="addCustomer()">Change  Data</button><ul>'  +                                              '<li  ng-­‐repeat="cust  in  customers">{{  cust.name  }}</li></ul>'                  };          });   <div  isolate-­‐scope-­‐with-­‐controller></div>  

Page 30: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Transclusion Inclusion  of  a  document  or  part  of  a  document   into  another  document  by  reference    

hKp://en.wikipedia.org/wiki/Transclusion  

Page 31: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

<html>          <body>                                  </body>  </html>  

 <div>                  Hello!    </div>  

Page 32: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

myDirec've  

<div  class="container">                      Content  provided  by  consumer  of          direc6ve    </div>      

Page 33: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

myDirec've  

<div  class="container"  ng-­‐transclude>                          Content  provided  by  consumer              of  direc6ve      </div>      

<html>      <body>                <my-­‐direc6ve>                      </my-­‐direc6ve>        </body>  </html>  

 <div>                  Hello!    </div>  

<div  class="container">          <div>                  Hello          </div>  </div>  

Page 34: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Agenda •  The  Role  of  Direc6ves  •  Peeking  Under  the  Hood  •  Shared  vs.  Isolate  Scope  •  Linking  to  the  DOM  •  Controller  Love  •  Direc've  Examples  

Page 35: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

hKps://github.com/DanWahlin/CustomerManagerStandard  

Page 36: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

Find  more              ngularJS  content  at:  

Blog h;p://weblogs.asp.net/dwahlin Twi;er

@DanWahlin  

Page 37: Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014