Building Custom 
AngularJS Direc6ves 
Dan 
Wahlin
Dan Wahlin 
Blog 
h;p://weblogs.asp.net/dwahlin 
Twi;er 
@DanWahlin
D
1
@ = 
&
Transclusion
Agenda 
• The 
Role 
of 
Direc6ves 
• Peeking 
Under 
the 
Hood 
• Shared 
vs. 
Isolate 
Scope 
• Linking 
to 
the 
DOM 
• Controller 
Love 
• Direc6ve 
Examples
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*
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 
-­‐-­‐>
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
Agenda 
• The 
Role 
of 
Direc6ves 
• Peeking 
Under 
the 
Hood 
• Shared 
vs. 
Isolate 
Scope 
• Linking 
to 
the 
DOM 
• Controller 
Love 
• Direc6ve 
Examples
templateUrl 
restrict 
template 
scope 
controller 
link
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
Agenda 
• The 
Role 
of 
Direc6ves 
• Peeking 
Under 
the 
Hood 
• Shared 
vs. 
Isolate 
Scope 
• Linking 
to 
the 
DOM 
• Controller 
Love 
• Direc6ve 
Examples
Parent 
Scope 
Shared Scope 
Child 
Scope
Isolate Scope
Wall 
Blocks 
Parent 
Scope 
Parent 
Scope 
Child 
Scope
Shared 
Scope 
Isolate 
Scope 
Controller 
$scope.customers=[]; 
Shared 
$scope.customers=[]; 
Direc've 
Depends 
on 
parent 
scope 
Controller 
$scope.customers=[]; 
Not 
Shared 
$scope.customers=[]; 
$scope.isolated 
= 
true; 
Direc've 
Isolated 
from 
parent 
scope
hKp://codepen.io/danwahlin
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>
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!
@ 
isolate 
scope 
property 
$scope.first='James'; 
<my-­‐directive 
name="{{first}}" 
/> 
Hi, 
I'm 
Dan 
@ 
scope: 
{ 
name: 
'@' 
} 
Direc've 
Direc6ve 
can 
access 
a 
string 
value 
String 
with 
one-­‐way 
binding
= 
isolate 
scope 
property 
$scope.person={name:'Dan'}; 
<my-­‐directive 
customer="person" 
/> 
Hi, 
I'm 
Dan 
= 
scope: 
{ 
customer: 
'=' 
} 
No, 
you're 
Jim 
Direc've 
Two-­‐way 
binding 
created 
Bi-­‐direc6onal 
Binding
& 
isolate 
scope 
property 
$scope.click=func6on() 
{ 
}; 
Call 
me 
back 
at: 
123-­‐1234 
<my-­‐directive 
action="click()" 
/> 
& 
scope: 
{ 
ac6on: 
'&' 
} 
Calling 
123-­‐1234 
Direc've 
Can 
invoke 
external 
func6on 
Func6on 
Callback
@ 
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()" 
/>
Agenda 
• The 
Role 
of 
Direc6ves 
• Peeking 
Under 
the 
Hood 
• Shared 
vs. 
Isolate 
Scope 
• Linking 
to 
the 
DOM 
• Controller 
Love 
• Examples
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>
Agenda 
• The 
Role 
of 
Direc6ves 
• Peeking 
Under 
the 
Hood 
• Shared 
vs. 
Isolate 
Scope 
• Linking 
to 
the 
DOM 
• Controller 
Love 
• Direc6ve 
Examples
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>
Transclusion 
Inclusion of a document or part of a document 
into another document by reference 
hKp://en.wikipedia.org/wiki/Transclusion
<html> 
<body> 
</body> 
</html> 
<div> 
Hello! 
</div>
myDirec've 
<div 
class="container"> 
Content 
provided 
by 
consumer 
of 
direc6ve 
</div>
myDirec've 
<div 
class="container" 
ng-­‐transclude> 
Content 
provided 
by 
consumer 
of 
direc6ve 
</div> 
<html> 
<body> 
<my-­‐direc6ve> 
<div 
class="container"> 
<div> 
<div> 
Hello 
</div> 
</div> 
Hello! 
</div> 
</my-­‐direc6ve> 
</body> 
</html>
Agenda 
• The 
Role 
of 
Direc6ves 
• Peeking 
Under 
the 
Hood 
• Shared 
vs. 
Isolate 
Scope 
• Linking 
to 
the 
DOM 
• Controller 
Love 
• Direc've 
Examples
hKps://github.com/DanWahlin/CustomerManagerStandard
Find more ngularJS content at: 
Blog 
h;p://weblogs.asp.net/dwahlin 
Twi;er 
@DanWahlin
Building Custom AngularJS Directives - A Step-by-Step Guide - Dan Wahlin | FalafelCON 2014

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

  • 1.
    Building Custom AngularJSDirec6ves Dan Wahlin
  • 2.
    Dan Wahlin Blog h;p://weblogs.asp.net/dwahlin Twi;er @DanWahlin
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
    Agenda • The Role of Direc6ves • Peeking Under the Hood • Shared vs. Isolate Scope • Linking to the DOM • Controller Love • Direc6ve Examples
  • 8.
    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*
  • 9.
    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 -­‐-­‐>
  • 10.
    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
  • 11.
    Agenda • The Role of Direc6ves • Peeking Under the Hood • Shared vs. Isolate Scope • Linking to the DOM • Controller Love • Direc6ve Examples
  • 12.
    templateUrl restrict template scope controller link
  • 13.
    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
  • 14.
    Agenda • The Role of Direc6ves • Peeking Under the Hood • Shared vs. Isolate Scope • Linking to the DOM • Controller Love • Direc6ve Examples
  • 15.
    Parent Scope SharedScope Child Scope
  • 16.
  • 17.
    Wall Blocks Parent Scope Parent Scope Child Scope
  • 18.
    Shared Scope Isolate Scope Controller $scope.customers=[]; Shared $scope.customers=[]; Direc've Depends on parent scope Controller $scope.customers=[]; Not Shared $scope.customers=[]; $scope.isolated = true; Direc've Isolated from parent scope
  • 19.
  • 20.
    Shared Scope Direc6veExample 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>
  • 21.
    Isola6ng Scope inDirec6ves 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!
  • 22.
    @ isolate scope property $scope.first='James'; <my-­‐directive name="{{first}}" /> Hi, I'm Dan @ scope: { name: '@' } Direc've Direc6ve can access a string value String with one-­‐way binding
  • 23.
    = isolate scope property $scope.person={name:'Dan'}; <my-­‐directive customer="person" /> Hi, I'm Dan = scope: { customer: '=' } No, you're Jim Direc've Two-­‐way binding created Bi-­‐direc6onal Binding
  • 24.
    & isolate scope property $scope.click=func6on() { }; Call me back at: 123-­‐1234 <my-­‐directive action="click()" /> & scope: { ac6on: '&' } Calling 123-­‐1234 Direc've Can invoke external func6on Func6on Callback
  • 25.
    @ 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()" />
  • 26.
    Agenda • The Role of Direc6ves • Peeking Under the Hood • Shared vs. Isolate Scope • Linking to the DOM • Controller Love • Examples
  • 27.
    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>
  • 28.
    Agenda • The Role of Direc6ves • Peeking Under the Hood • Shared vs. Isolate Scope • Linking to the DOM • Controller Love • Direc6ve Examples
  • 29.
    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>
  • 30.
    Transclusion Inclusion ofa document or part of a document into another document by reference hKp://en.wikipedia.org/wiki/Transclusion
  • 31.
    <html> <body> </body> </html> <div> Hello! </div>
  • 32.
    myDirec've <div class="container"> Content provided by consumer of direc6ve </div>
  • 33.
    myDirec've <div class="container" ng-­‐transclude> Content provided by consumer of direc6ve </div> <html> <body> <my-­‐direc6ve> <div class="container"> <div> <div> Hello </div> </div> Hello! </div> </my-­‐direc6ve> </body> </html>
  • 34.
    Agenda • The Role of Direc6ves • Peeking Under the Hood • Shared vs. Isolate Scope • Linking to the DOM • Controller Love • Direc've Examples
  • 35.
  • 36.
    Find more ngularJScontent at: Blog h;p://weblogs.asp.net/dwahlin Twi;er @DanWahlin