SlideShare a Scribd company logo
AngularJS Directives
AngularJS Directives
<tabs>
<pane title="Localization">...</pane>
<pane title="Pluralization">
<ng-pluralize count="beerCount" when="beerForms"></ng-pluralize>
</pane>
</tabs>
AngularJS Directives
AngularJS Directives
<span my-dir="exp"></span>
<span class="my-dir:exp;"></span>
<my-dir></my-dir>

Code
var app = angular.module("app", []);
app.directive('copyright', function () {
return {
restrict: 'M',
compile: function (element) {
element.text('Copyright 2013 Eyal Vardi');
}
};
});
<div draggable>Hello</div>
app.directive('draggable', function ($document) {
var startX = 0, startY = 0, x = 0, y = 0;
return function(scope, element, attr) {
element.css({ position: 'relative', cursor: 'pointer' });
element.bind('mousedown', function(event) {...});
});
<script src="/Scripts/angular.min.js"></script>
app.directive('importantBackgroundColor', function () {
return {
restrict: 'C',
priority: -99999, // we want this to be run last
// we don't use compile because we want to do this
// at the last possible minute
link: function (scope, element, attribs) {
element.css('background-color', attribs.color);
}
};
});
AngularJS Directives
myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
priority: 0,
terminal: false,
template: '<div></div>',
templateUrl:'directive.html',
replace: false,
transclude: false,
restrict: 'A',
scope: false,
require: '^?ngModel'
controller: function($scope, $element, $attrs, $transclude, Injectables) { ... },
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) { ... },
post: function postLink(scope, iElement, iAttrs, controller) { ... }
}
},
link: function postLink(scope, iElement, iAttrs, controller) { ... }
};
return directiveDefinitionObject;
});
<div ng-controller="MyCtrl">
<ul>
<li ng-repeat="n in names">{{n}}</li>
</ul>
</div>
First the HTML is parsed into DOM
using the standard browser API.
Once all directives for a given
DOM element have been identified
they are sorted by priority and their
compile() functions are
executed.
DOM + link($scope)
Live binding between the
scope and the DOM
Register any listeners on the
elements and set up any
watches with the scope.
var $compile = ...; // injected into your code
var scope = ...;
var html = '<div ng-bind="exp"></div>';
// Step 1: parse HTML into DOM element
var template = angular.element(html);
// Step 2: compile the template
var linkFn = $compile(template);
// Step 3: link the compiled template with the
scope.
var element = linkFn(scope);
// Step 4: Append to DOM (optional)
parent.appendChild(element);
<div directive1 directive2>
<div directive3>
Hello World...
</div>
</div>
$compile start
$compile end
 Factory func
 Template
 Compile
 Controller
 preLink
 postLink
 Factory func
 No Template
 Compile
 Controller
 preLink
 postLink
 Factory func
 Template
 Compile
 Controller
 preLink
 postLink
terminal
<div directive1 directive2>
<div directive3>
Hello World...
</div>
</div>
$compile start
$compile end
 Factory func
 Template
 Compile
 Controller
 preLink
 postLink
 Factory func
 Factory func
 Template
 Compile
 Terminal = true
 Priority = 1001
 Factory func
 Template
 Compile
 Controller
 preLink
 postLink
<ul>
<li ng-repeat="x in [1,2,3,4]"
directive-name> {{x}} </li>
</ul>
AngularJS Directives
require: [ '^?ngModel', '^?Form']
function compile(tElement, tAttrs, transclude) { ... }
function link( scope, iElement, iAttrs, controller ) { ... }
function linkingFn(scope, elm, attrs, ctrl) {
// get the attribute value
console.log(attrs.ngModel);
// change the attribute
attrs.$set('ngModel', 'new value');
// observe changes to interpolated attribute
attrs.$observe('ngModel', function(value) {
console.log('ngModel has changed value to ' + value); });
}
AngularJS Directives
childScope.aString === 'parent string'
childScope.anArray[1] === 20
childScope.anObject.property1 === 'parent prop1'
childScope.aFunction() === 'parent output
childScope.aString = 'child string';childScope.aString = 'child string';
childScope.anArray[1] = '22';
childScope.anObject.property1 = 'child prop1';
This new property
hides / shadows the
parentScope property
with the same name.
childScope.anArray = [100,555];
childScope.anObject = { name: 'Mark', country: 'USA' };
AngularJS Directives
$scope.myPrimitive = 50;
$scope.myObject = { aNumber: 11 };
<script type="text/ng-template" id="/tpl1.html">
<input ng-model="myPrimitive">
</script>
<div ng-include src="'/tpl1.html'"></div>
<script type="text/ng-template" id="/tpl2.html">
<input ng-model="myObject.aNumber">
</script>
<div ng-include src="'/tpl2.html'"></div>
$scope.myPrimitive = 77;
$scope.myObject = { aNumber: 11 };
<script type="text/ng-template" id="/tpl1.html">
<input ng-model="myPrimitive">
</script>
<div ng-include src="'/tpl1.html'"></div>
<script type="text/ng-template" id="/tpl2.html">
<input ng-model="myObject.aNumber">
</script>
<div ng-include src="'/tpl2.html'"></div>
$scope.myPrimitive = 50;
$scope.myObject = { aNumber: 99 };
<script type="text/ng-template" id="/tpl1.html">
<input ng-model="myPrimitive">
</script>
<div ng-include src="'/tpl1.html'"></div>
<script type="text/ng-template" id="/tpl2.html">
<input ng-model="myObject.aNumber">
</script>
<div ng-include src="'/tpl2.html'"></div>
99
50
<script type="text/ng-template" id="/tpl1.html">
<input ng-model="$parent.myPrimitive">
</script>
<div ng-include src="'/tpl1.html'"></div>
<script type="text/ng-template" id="/tpl2.html">
<input ng-model="myObject.aNumber">
</script>
<div ng-include src="'/tpl2.html'"></div>
Typing (say, "22")
AngularJS Directives
<my-directive
interpolated ="Hello {{parentProp1}}"
twowayBinding ="parentProp2"
isolated-exp-foo ="updateFoo(newFoo)"
>
...
</my-directive>
scope: {
interpolatedProp: '@interpolated', // One-way Binding
twowayBindingProp: '=twowayBinding', // Two-way Binding
isolatedExpFooMeto: '&isolatedExpFoo' // Function Binding
}
// Option II
scope: {
interpolated: '@' ,
twowayBinding: '=' ,
isolatedExpFoo: '&'
}
Code
local scope = DOM attribute
local scope = parent scope
execute an expression in the
context of the parent scope
AngularJS Directives
AngularJS Directives
<div ng-controller="Ctrl3">
Title: <input ng-model="title"> <br>
Text: <textarea ng-model="text"></textarea>
<div class="zippy" zippy-title="Details: {{title}}">{{text}}</div>
</div>
angular.module('zippyModule', [])
.directive('zippy', function () {
return {
restrict: 'C',
replace: true,
transclude: true,
scope: { title: '@zippyTitle' },
template: '<div>' +
'<div class="title">{{title}}</div>' +
'<div class="body" ng-transclude></div>' +
'</div>',
link: function(scope, element, attrs) {...}
};
});
Code
Code
AngularJS Directives
AngularJS Directives
AngularJS.org
The Nuances of Scope Prototypal Inheritance
AngularJS Sticky Notes Pt 2 – Isolated Scope
Transclude in AngularJS

More Related Content

AngularJS Directives

  • 3. <tabs> <pane title="Localization">...</pane> <pane title="Pluralization"> <ng-pluralize count="beerCount" when="beerForms"></ng-pluralize> </pane> </tabs>
  • 7. var app = angular.module("app", []); app.directive('copyright', function () { return { restrict: 'M', compile: function (element) { element.text('Copyright 2013 Eyal Vardi'); } }; }); <!-- directive: copyright --> <!-- Copyright 2013 Eyal Vardi -->
  • 8. <div draggable>Hello</div> app.directive('draggable', function ($document) { var startX = 0, startY = 0, x = 0, y = 0; return function(scope, element, attr) { element.css({ position: 'relative', cursor: 'pointer' }); element.bind('mousedown', function(event) {...}); });
  • 9. <script src="/Scripts/angular.min.js"></script> app.directive('importantBackgroundColor', function () { return { restrict: 'C', priority: -99999, // we want this to be run last // we don't use compile because we want to do this // at the last possible minute link: function (scope, element, attribs) { element.css('background-color', attribs.color); } }; });
  • 11. myModule.directive('directiveName', function factory(injectables) { var directiveDefinitionObject = { priority: 0, terminal: false, template: '<div></div>', templateUrl:'directive.html', replace: false, transclude: false, restrict: 'A', scope: false, require: '^?ngModel' controller: function($scope, $element, $attrs, $transclude, Injectables) { ... }, compile: function compile(tElement, tAttrs, transclude) { return { pre: function preLink(scope, iElement, iAttrs, controller) { ... }, post: function postLink(scope, iElement, iAttrs, controller) { ... } } }, link: function postLink(scope, iElement, iAttrs, controller) { ... } }; return directiveDefinitionObject; });
  • 12. <div ng-controller="MyCtrl"> <ul> <li ng-repeat="n in names">{{n}}</li> </ul> </div> First the HTML is parsed into DOM using the standard browser API. Once all directives for a given DOM element have been identified they are sorted by priority and their compile() functions are executed. DOM + link($scope) Live binding between the scope and the DOM Register any listeners on the elements and set up any watches with the scope. var $compile = ...; // injected into your code var scope = ...; var html = '<div ng-bind="exp"></div>'; // Step 1: parse HTML into DOM element var template = angular.element(html); // Step 2: compile the template var linkFn = $compile(template); // Step 3: link the compiled template with the scope. var element = linkFn(scope); // Step 4: Append to DOM (optional) parent.appendChild(element);
  • 13. <div directive1 directive2> <div directive3> Hello World... </div> </div> $compile start $compile end  Factory func  Template  Compile  Controller  preLink  postLink  Factory func  No Template  Compile  Controller  preLink  postLink  Factory func  Template  Compile  Controller  preLink  postLink
  • 14. terminal <div directive1 directive2> <div directive3> Hello World... </div> </div> $compile start $compile end  Factory func  Template  Compile  Controller  preLink  postLink  Factory func  Factory func  Template  Compile  Terminal = true  Priority = 1001
  • 15.  Factory func  Template  Compile  Controller  preLink  postLink <ul> <li ng-repeat="x in [1,2,3,4]" directive-name> {{x}} </li> </ul>
  • 18. function compile(tElement, tAttrs, transclude) { ... }
  • 19. function link( scope, iElement, iAttrs, controller ) { ... }
  • 20. function linkingFn(scope, elm, attrs, ctrl) { // get the attribute value console.log(attrs.ngModel); // change the attribute attrs.$set('ngModel', 'new value'); // observe changes to interpolated attribute attrs.$observe('ngModel', function(value) { console.log('ngModel has changed value to ' + value); }); }
  • 22. childScope.aString === 'parent string' childScope.anArray[1] === 20 childScope.anObject.property1 === 'parent prop1' childScope.aFunction() === 'parent output
  • 23. childScope.aString = 'child string';childScope.aString = 'child string'; childScope.anArray[1] = '22'; childScope.anObject.property1 = 'child prop1'; This new property hides / shadows the parentScope property with the same name.
  • 24. childScope.anArray = [100,555]; childScope.anObject = { name: 'Mark', country: 'USA' };
  • 26. $scope.myPrimitive = 50; $scope.myObject = { aNumber: 11 }; <script type="text/ng-template" id="/tpl1.html"> <input ng-model="myPrimitive"> </script> <div ng-include src="'/tpl1.html'"></div> <script type="text/ng-template" id="/tpl2.html"> <input ng-model="myObject.aNumber"> </script> <div ng-include src="'/tpl2.html'"></div>
  • 27. $scope.myPrimitive = 77; $scope.myObject = { aNumber: 11 }; <script type="text/ng-template" id="/tpl1.html"> <input ng-model="myPrimitive"> </script> <div ng-include src="'/tpl1.html'"></div> <script type="text/ng-template" id="/tpl2.html"> <input ng-model="myObject.aNumber"> </script> <div ng-include src="'/tpl2.html'"></div>
  • 28. $scope.myPrimitive = 50; $scope.myObject = { aNumber: 99 }; <script type="text/ng-template" id="/tpl1.html"> <input ng-model="myPrimitive"> </script> <div ng-include src="'/tpl1.html'"></div> <script type="text/ng-template" id="/tpl2.html"> <input ng-model="myObject.aNumber"> </script> <div ng-include src="'/tpl2.html'"></div> 99 50
  • 29. <script type="text/ng-template" id="/tpl1.html"> <input ng-model="$parent.myPrimitive"> </script> <div ng-include src="'/tpl1.html'"></div> <script type="text/ng-template" id="/tpl2.html"> <input ng-model="myObject.aNumber"> </script> <div ng-include src="'/tpl2.html'"></div> Typing (say, "22")
  • 31. <my-directive interpolated ="Hello {{parentProp1}}" twowayBinding ="parentProp2" isolated-exp-foo ="updateFoo(newFoo)" > ... </my-directive> scope: { interpolatedProp: '@interpolated', // One-way Binding twowayBindingProp: '=twowayBinding', // Two-way Binding isolatedExpFooMeto: '&isolatedExpFoo' // Function Binding } // Option II scope: { interpolated: '@' , twowayBinding: '=' , isolatedExpFoo: '&' } Code local scope = DOM attribute local scope = parent scope execute an expression in the context of the parent scope
  • 34. <div ng-controller="Ctrl3"> Title: <input ng-model="title"> <br> Text: <textarea ng-model="text"></textarea> <div class="zippy" zippy-title="Details: {{title}}">{{text}}</div> </div> angular.module('zippyModule', []) .directive('zippy', function () { return { restrict: 'C', replace: true, transclude: true, scope: { title: '@zippyTitle' }, template: '<div>' + '<div class="title">{{title}}</div>' + '<div class="body" ng-transclude></div>' + '</div>', link: function(scope, element, attrs) {...} }; }); Code
  • 35. Code
  • 38. AngularJS.org The Nuances of Scope Prototypal Inheritance AngularJS Sticky Notes Pt 2 – Isolated Scope Transclude in AngularJS