Download - Workshop 13: AngularJS Parte II
![Page 1: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/1.jpg)
Front End Workshops
XII. AngularJS - Part 2
Enrique Oriol Bermú[email protected]
Héctor [email protected]
![Page 2: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/2.jpg)
Overview
“AngularJS lets you write client-side web
applications as if you had a smarter browser”
![Page 3: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/3.jpg)
Overview
“AngularJS is easy”
AngularJS learning curve
AngularJS is
amazing... and
hard as hell
![Page 4: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/4.jpg)
Content
● Digest Cycle
● Services
● Dependency Injection
● Routes
● Building Filters
● Building Directives
![Page 5: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/5.jpg)
Digest Cycle
the tech behind 2 way data binding magic
![Page 6: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/6.jpg)
Digest cycle
User event(ng-click)
Sync work in controllers
Async work in $http, $timeout and $interval
scope.$apply Start from root scope
Check allwatchers on
scope
more scopes? Update UI
value changed
no change
switch to scope and continue checking
everything’sdone
$digest phase
![Page 7: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/7.jpg)
Digest cycle
What about async events?
If you want to update view after receiving async event, you should force a $apply call.
Don’t do it directly: use $timeout
// Somewhere, an async handler
var handler = function(){
$rootScope.$emit("changeContent");
};
//in your controller
$rootScope.$on("changeContent", function(){
console.log("rootScope event has been fired");
$timeout(function(){ $scope.data = "Data should change"; });
});
![Page 8: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/8.jpg)
Services
Where business logic lives
![Page 9: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/9.jpg)
Services
Services refers to injectable objects whose API is defined by the developer (not the framework)
Reusable business logic, view independant
![Page 10: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/10.jpg)
Services
Singleton objects
Once defined, it can be injected into other angular components like controllers, directives and services
![Page 11: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/11.jpg)
Registering Services
Module exposes 5 methods to instruct the injector how to evaluate our code
var myApp = angular.module('myApp', [''])
.constant('myConstant', {})
.value('myValue', {})
.service('myService', function(){})
.factory('myService', function(){})
.provider('myService', function(){})
![Page 12: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/12.jpg)
Registering Services
Application life-cycle splits in 2 phases
● Configuration phase (app bootstrap)
○ No services
○ Configure and instantiate providers
● Run phase (after config)
○ No Providers interaction○ Services start being created
![Page 13: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/13.jpg)
● For simple values of any type● Do not accept DI / being configured● Can be injected into the config function
myApp.constant('SERVERS',{ DEVELOPMENT: "http://localhost:8080/app", PRODUCTION:"http://myDomain.com/app"});
Constant
myApp.config(function(SERVERS){
console.log(SERVERS.PRODUCTION);
});
myApp.run(function(SERVERS){
console.log(SERVERS.DEVELOPMENT);
})
Definition
CONFIG USAGE RUN USAGE
![Page 14: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/14.jpg)
● Simple objects or primitives● Do not accept DI / being configured
myApp.value('randomize',function(){ return Math.floor(Math.random()*10000);})
myApp.value('token','a1234567890');
myApp.value('User',{'id': 'someId'})
Value
myApp.run(function(randomize, User){
var num = randomize();
User.id = num;
});
Definition
USAGE
![Page 15: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/15.jpg)
● Constructor function that will be instantiated (internally invokes it with new)
● Cannot being configured● Arguments represents DEPENDENCIES to be injected
myApp.service('AuthBearer', ['token', function(token) {
this.authValue = "bearer " + token;
}]);
Service
myApp.run(function(AuthBearer){
console.log(AuthBearer.authValue);
})
Definition
USAGE
myApp.value('token','a1234567890');
TOKEN is INJECTED!!!
![Page 16: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/16.jpg)
● Uses DI, No config● Allows service initialization
myApp.factory('apiToken', ['$window', 'clientId', function apiTokenFactory($window, clientId) {
var encrypt = function(data1, data2) {
// NSA-proof encryption algorithm:
return (data1 + ':' + data2).toUpperCase();
};
var secret = $window.localStorage.getItem('myApp.secret');
var apiToken = encrypt(clientId, secret);
return apiToken;
}]);
Factory
myApp.run(function(apiToken)
{
console.log(apiToken);
})
Definition
USAGE
![Page 17: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/17.jpg)
● Uses DI● Exposes API for service config before app starts (config phase)● $get method is a factory function, that creates our service
myApp.provider('logger', function(){
var logToConsole = false;
this.enableConsole = function(flag){
logToConsole = flag;
};
this.$get = function(){
return {
debug: function(msg){ if(logToConsole){ console.log(msg);} }
};
};
})
Provider
Definition
![Page 18: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/18.jpg)
Provider
myApp.config(function(loggerProvider){
loggerProvider.enableConsole(true);
})
CONFIGURATION
myApp.run(function(logger){
logger.debug('Hello world');
})
USAGE
myApp.provider('logger', function(){
var logToConsole = false;
this.enableConsole = function(flag){
logToConsole = flag;
};
this.$get = function(){
return {
debug: function(msg){ if(logToConsole){ console.log(msg);} }
};
};
})
REMEMBER
![Page 19: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/19.jpg)
myApp.provider('logger', function(){
var logToConsole = false;
this.enableConsole = function(flag){
logToConsole = flag;
};
this.$get =
function(){
return {
debug: function(msg){
if(logToConsole){ console.log(msg);}
}
};
};
});
Provider shorthands
Provider
Factory
Service
![Page 20: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/20.jpg)
Dependency Injection
Pervasive pattern along angular
![Page 21: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/21.jpg)
Dependency Injection
Software design pattern that deals with how
components get hold of their dependencies
![Page 22: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/22.jpg)
Dependency Injection
The Angular injector subsystem is in charge of
creating components,
resolving their dependencies,
and providing them to other components as requested.
![Page 23: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/23.jpg)
Dependency Injection
The key players are the
provide & injector
services
The magic behind
![Page 24: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/24.jpg)
Dependency Injection
We register our code on the
injector with the provide service
https://docs.angularjs.org/api/auto/service/$provide
The magic behind
![Page 25: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/25.jpg)
Dependency Injection
We must provide a
key as the first argument
The magic behind
![Page 26: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/26.jpg)
Dependency Injection
The injector keeps our code in an
internal object called
providerCache
The magic behind
![Page 27: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/27.jpg)
Dependency Injection
We use the injector to
retrieve object instances
https://docs.angularjs.org/api/auto/service/$injector
The magic behind
![Page 28: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/28.jpg)
Dependency Injection
First time we inject a service, the
injector evaluates the code
and stores the result
in an instanceCache object
The magic behind
![Page 29: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/29.jpg)
Dependency Injection
When injecting a service,
injector always look first
into instanceCache
The magic behind
![Page 30: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/30.jpg)
Dependency Injection
That’s why our services
are singletons
The magic behind
![Page 31: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/31.jpg)
Dependency Injection
Components, controllers and run
accept any service DI (not providers)
config can be injected
with provider and constant components
How to use it
![Page 32: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/32.jpg)
Dependency Injection
3 ways to use DI:
Implicit Annotation
$inject Property Annotation
Inline Array Annotation
How to use it
![Page 33: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/33.jpg)
Dependency Injection
Implicit Annotation
How to use it
myApp.controller('MyCtrl', function($scope, logger) {
// ...
});
The Simplest way
If we minify our code, service names as arguments will be renamed, and app will
break.var MyController = function($scope, logger) {
// ...
}
myApp.controller('MyCtrl', MyController]);
![Page 34: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/34.jpg)
Dependency Injection
$inject property Annotation
How to use it
var MyController = function($scope, logger) {
// ...
}
MyController.$inject = ['$scope', 'logger'];
myApp.controller('MyCtrl', MyController);
The Long way
Order of parameters must MATCH
![Page 35: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/35.jpg)
Dependency Injection
Inline Array Annotation
How to use it
myApp.controller('MyCtrl', ['$scope', 'logger', function($scope, logger)
{
// ...
}]);
The prefered way
var MyController = function($scope, logger) {
// ...
}
myApp.controller('MyCtrl', ['$scope', 'logger',
MyController]);Order of parameters must MATCH
![Page 36: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/36.jpg)
Routes
Navigating Through Views
![Page 37: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/37.jpg)
Routes
2 common routing libs
● ngRoute https://docs.angularjs.org/api/ngRoute/service/$route ○ Official○ Separated in ngRoute module○ Only one navigation view per application
● ui-router https://angular-ui.github.io/ui-router/
○ Community chosen○ More powerful○ More flexible
![Page 38: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/38.jpg)
ui-router
based on states concept
can use routes
other behaviours
![Page 39: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/39.jpg)
ui-router
What is a ‘state’?
A place in the app, in terms of UI and navigation
Describes how the UI looks like and what does at that place
States are bound to named, nested and parallel views
![Page 40: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/40.jpg)
ui-router
Installation
$ bower install angular-ui-router
<script src="angular.js"></script>
<script src="angular-ui-router.js"></script>
angular.module('myApp', ['ui.router']);
Get Package
Include Script
Import Module
![Page 41: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/41.jpg)
ui-router
Simple State
angular.module('myApp', ['ui.router'])
.config(function($stateProvider){
$stateProvider
.state('home', {
url: '/home.html',
templateUrl: 'views/home.html'
});
});
<!-- index.html -->
<head>
<!--...stuff...-->
</head>
<body ng-app>
<!--...stuff...-->
<ui-view></ui-view>
</body>
Defining State Directive ui-view
![Page 42: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/42.jpg)
ui-router
$stateProvider
$state is a service defined with provider method
that gives us $stateProvider to prepare $state at config phase
$state is the ui-router service to handle states
http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state
![Page 43: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/43.jpg)
ui-router
Navigation
<body>
<div ui-sref='home'>Navigate!</div>
<ui-view></ui-view>
</body>
<body ng-controller="Ctrl">
<div ng-click="navigate()">Navigate!</div>
<ui-view></ui-view>
</body>
NAV THROUGH VIEW NAV THROUGH CONTROLLER
myApp.controller('Ctrl', function($scope, $state){
$scope.navigate = function(){
$state.go('home');
}
})
link href also works, but AngularJS introduces #: <a href='#/home'></a>
![Page 44: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/44.jpg)
ui-router
Some state options
.config(function($stateProvider){
$stateProvider
.state('home', {
url: '/home.html',
templateUrl: 'views/home.html',
controller: 'HomeCtrl',
data:{
level: 'PRO'
}
});
});
.controller('HomeCtrl', function($scope, $state){
$scope.message = "Hi world!, you belong to " +
$state.current.data.level + " level";
})
![Page 45: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/45.jpg)
ui-router
Parameters
.config(function($stateProvider){
$stateProvider
.state('home', {
url: '/home/:username',
templateUrl: 'views/home.html',
controller: 'HomeCtrl'
});
});
.controller('HomeCtrl', function($scope, $stateParams){
$scope.message = "Hi " + $stateParams.username;
})
.controller('Ctrl', function($scope, $state){
$scope.navigate = function(){
$state.go('home', {username: "Marqués"});
}
})
<button ui-sref="home({username:'Bob'})">
Navigate using ui-sref
</button>
![Page 46: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/46.jpg)
ui-router
.config(function($stateProvider){
$stateProvider
.state('home', {
url: '/home/:username',
templateUrl: 'views/home.html',
controller: 'HomeCtrl',
data:{ level: 'PRO'}
})
.state('home.profile', {
url: '/profile',
templateUrl: 'views/profile.html',
controller: 'ProfileCtrl'
})
});
Nested views.controller('HomeCtrl', function($scope, $state, $stateParams){
$scope.homeMsg = "Home, sweet home " + $stateParams.username;
})
.controller('ProfileCtrl', function($scope, $state, $stateParams){
$scope.user = {
name: $stateParams.username,
level: $state.current.data.level
};
})
<button ui-sref="home.profile({username:'Bob'})"> </button>
![Page 47: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/47.jpg)
ui-router
.config(function($stateProvider){
$stateProvider
.state('home', {
views:{
"": { template: '<ui-view></ui-view>' },
"header": {
templateUrl: 'views/header.html',
controller: 'HeaderCtrl'
},
"footer": { template:"<div class='vCentered'>All rights reserved</div>" }
}
})
})
Named views
<body ng-controller="Ctrl">
<div class="container">
<ui-view></ui-view>
<div ui-view="header"></div>
<div ui-view="footer"></div>
<div>
</body>
ui-view directive can be used as Element or as Attribute
![Page 48: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/48.jpg)
ui-router
.config(function($stateProvider, $urlRouterProvider){
$stateProvider.state(...)
$urlRouterProvider.otherwise('#/home') //this is a URL
})
Redirections
.run(function($state){
$state.transitionTo('home);
});
Always that Url is unknown
At Launch
![Page 49: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/49.jpg)
use state property abstract:true
abstract states cannot be directly activated
abstract states can have controller
Useful for nested views
ui-router
Abstract states
![Page 50: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/50.jpg)
● abstract states
● nested states
● named states
ui-router
Let’s see a full example with:
![Page 51: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/51.jpg)
ui-router
State resolve and callbacks
.state('home', {
resolve: {user: function(){}}, //where function returns a promise
onEnter: function(user){},
onExit: function(user){}
});
![Page 52: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/52.jpg)
ui-router
staterequested $stateChangeStart
$stateChangeSuccess
ui-view kicks in$viewContentLoaded
Done
State Life Cycle & Events
$stateChangeError
$stateNotFound
onload function
![Page 53: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/53.jpg)
Filters
— AND $Filter.(‘filter’) —
![Page 54: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/54.jpg)
Filters
Pre-defined filters: currency, number, date, lowercase, orderBy, filter …● We can apply several filters to the same expression
Format:{{ expression | filter:argument1:argument2 | filter2 … }}
Some examples:{{ 5 | currency: ”€”, 2}} >> €5.00{{ 5 | currency: ””, 2}} + “ €“ >> 5.00 €{{ “hello” | uppercase }} >> HELLO
![Page 55: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/55.jpg)
Custom Filter
app.filter('filtername', function() { return function(input) { return input + ‘some text’; };
DOM filter{{ input_expression | filtername }}
Controller filter$filter(‘filtername’)(input_expression, argument);
![Page 56: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/56.jpg)
How filters work● Every binded expression will have a $watcher.
○ So don’t spare on filters if they improve your life.● Watchers are checked every digest loop, but only run on changes.
○ Filters take as much time as the function they run.● Optimization
○ Use one-way binding (::value) ○ If something won’t change, pre-process it, don’t filter it.○ Avoid DOM filters when possible○ Beware of dependencies, don’t introduce state.○ Preferably with strings
http://www.alexkras.com/11-tips-to-improve-angularjs-performance/
https://www.binpress.com/tutorial/speeding-up-angular-js-with-simple-optimizations/135
4
![Page 57: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/57.jpg)
Stateful Filters
Typical case: {{ 'TRANSLATIONID' | translate }}
● The ID never changes but the language does.● Used on ng-translate.
angular.module('myApp', []).filter('translate', ['translationService', function (translationService) { function translate(input) { chain_translated += translationService.getChain(input); return chain_translated; } translate.$stateful = true; return translate;}]);http://blog.thoughtram.io/angularjs/2014/11/19/exploring-angular-1.3-stateful-filters.html
![Page 58: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/58.jpg)
Directives
— DOM Manipulation —
![Page 59: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/59.jpg)
Directives
Main purpose:Directives are markers on a DOM element that tell Angular’s HTML “compiler” to
attach a certain behaviour to it (via event listeners).Structure● Snake and camelCase naming format● Restrict roles● Template vs. TemplateURL● Controller and controllerAs● Scope isolation● Functions
http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-i-the-fundamentals
![Page 60: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/60.jpg)
By intuition you may think that a directive is a component of the template.That being correct, it is more than that.
Directives can :● add or modify behaviour of elements● add real-time dynamism to elements >> two way data binding● add interactivity with the user● modify or complement other directives● add a complete element● provide code reutilization, for instance: animations, styles ...● connect elements data and behaviour
Directives
![Page 61: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/61.jpg)
Custom Directives: Naming format
Directives are meant to be part of the template so their naming format are restricted to HTML syntax.
Automatically, camelCase names are understood on the template as Snake names, see the example below:
app.directive(customDirective, function() { return { }});
<custom-directive></custom directive><x_custom_directive></x_custom_directive><data:custom:directive></data:custom:directive>
![Page 62: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/62.jpg)
Custom Directives: Roles
Directives can play different roles in the template:● Element, attribute, class or comment even. Restrictions should be
applied.● Element and attribute allow parameters.● More intuitive to use element, but attribute helps separating CSS.
app.directive(CustomDirective, function() { return { restrict: 'EACM', scope: {}, template: '<div class="sparkline"><h4>Hello world</h4></div>', controller: function (){}, controllerAs: ‘ctrl1’, link: function() {}, }});
WARNING: Compatibility issues
with C and M.
![Page 63: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/63.jpg)
template vs. templateURL
They are equivalent but templateURL is recommended.
● templateURL points to a file template (with path)
○ We can use a function previously defined
○ We can use import mechanisms from requireJS or ES6
● template is the template inline
template: '<div class="sparkline"><h4>Hello world</h4></div>', templateURL: 'path/to/template.html', templateURL: tpl,
![Page 64: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/64.jpg)
Custom directives: controller
Usually a directive is bound to a controller and this is achieved by defining or passing the controller to the directive.controller: function() {return;}
The controller is run after the template is compiled but before the DOM is completed and the scope linked between directives. So, variables has not been replaced and data-binding has not been performed.
DON’T MANIPULATE THE DOM HERE
The controller is meant to set the data necessary for the directive and interact with the rest of the application.
Think of it as the API for the directive.
![Page 65: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/65.jpg)
Custom directives: controllerAs
ControllerAs creates a variable in the directive’s scope that will hold the Controller’s scope:
ControllerAs: ‘ctrl1’,$scope.ctrl1.something
● Recommended for confusing namespaces● Avoids overlapping of variables with the same name● Identifies levels of inheritance● Using this becomes safer, but you might be using $scope already.
![Page 66: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/66.jpg)
@ Text binding passes string values and does one way binding. Allow interpolation as in the example above.
& One way or once: changes on the directive will not affect the parent scope. Think of it as a getter.Can be used to call external functions
= Two way passes objects and changes affect to both directive and higher scopes (all if not limited).It is the more magical one but it comes with a cost.
Custom directives: Binding stylesangular.module("myApp",[]) .directive("myDirective", function () { return { restrict: "A", scope: { text: "@myText", oneWayBind: "&myOneWayBind", twoWayBind: "=myTwoWayBind", name: "=" } }; }).controller("myController", function ($scope) { $scope.foo = {name: "zwerty"}; $scope.bar = "qwerty"; $scope.name = "name";});
<div ng-bind="myController"> <div my-directive my-text="hello {{ bar }}" my-two-way-bind="foo" my-one-way-bind="bar"> </div></div>
PAY ATENTION TO {{bar }} in my-text
https://umur.io/angularjs-directives-using-isolated-scope-with-attributes/
![Page 67: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/67.jpg)
More on binding styles
● ng-bind is one way.● ng-model is two way.● {{ var }} is similar to a one way binding, but it is dirty checked every digest
cycle. ○ Using {{::var}} we limit the checking to the first time (once)is one way.
● So {{ var }} is potentially slower than ng-model because the first is interpreted every digest cycle.
![Page 68: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/68.jpg)
By default a directive inherits the scope of his parent. For example an ng-controller:
div ng-controller="ParentController"> ParentController: <input type="text" ng-model="foo" /> <custom-directive></custom-directive></div>
Inheritance goes all the way to the upper level. And also affects siblings.
Custom directives: Scope inheritance
![Page 69: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/69.jpg)
If we initialize the property scope in the directive’s definition we achieve an isolated scope (at least partially):
scope: {},scope: true,scope: {foo: "..."}
Isolation is partial, but controlled, by the data-binding.
Nevertheless, inheritance is still happening as we can see in this example:http://codepen.io/hectorcanto/pen/JGzdoj
Custom directives: Isolated scope
![Page 70: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/70.jpg)
angular.module('directivesModule').directive('isolatedScopeWithController', function () { return { restrict: 'EA', scope: { datasource: '=', add: '&', }, controller: function ($scope) { ... $scope.addItem = function () { var name = 'New Item Added by Directive'; $scope.add( )(name); $scope.items.push({ name: name }); }; }, template: '<button ng-click="addItem()">Change Data</button><ul> <li ng-repeat="element in items">{{ element.name }}</li></ul>' };});
Custom directives: Isolated scope II
<div isolated-scope-with-controller datasource="items" add="addCostumer"></div>
![Page 71: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/71.jpg)
There are 3 types of functions, by order of execution:○ compile, controller and link
● Compile happens once, before the template is compiled.● The rest of functions is run once for each time the directive is used
■ For example in a ng-repeat of 4 elements, 4 loops○ Controller initialize the scope.○ Link happens when the linking is being made, by default after.○ We can divide link into two, pre-link and post-link
■ Pre-link happens before the element is linked to the scope■ Post-link happens just after, when the element affected is on the DOM.
● This is the most usual and potentially safest
Custom directives: functions
http://www.undefinednull.com/2014/07/07/practical-guide-to-prelink-postlink-and-controller-methods-of-angular-directives/
![Page 72: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/72.jpg)
Custom directives: link, prelink, postlink
● There are 4 arguments available for these functions (in this order)
○ scope, elements, attributes and controllers
● You can access the DOM, you have the element.
● By default use link directly, which is equivalent to post-link alone.
● Remember, if possible provide values as soon as you can.
○ Don’t wait to post-link, do it in the controller or in compile
● [post-]link is the View part where you have everything in place and you do
the last adjustments and decisions regarding the DOM.
![Page 73: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/73.jpg)
Custom directives: link, prelink, postlinkvar app = angular.module('app', []);app.directive('dad', function () { return { restrict: 'EA', template: '<div class="dad">{{greeting}}{{name}}'+ '<son></son>'+ '</div>', link: { pre: function(scope,elem,attr){ scope.name = 'Paul'; scope.greeting = 'Hey, I am '; } } };})
app.directive('son', function () { return { restrict: 'EA', template: '<div class="son">{{sonSays}}</div>', link: function(scope,elem,attr){ scope.sonSays = 'Hey, I am David, and my dad is '+ scope.name; } };});
<div ng-app="app"> <dad></dad></div>
Hey, I am PaulHey, I am David, and my dad is Paul
http://jsfiddle.net/shidhincr/Bpxn2/1/?utm_source=website&utm_medium=embed&utm_campaign=Bpxn2
![Page 74: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/74.jpg)
Custom directives: post-link,
● It is safe to manipulate the DOM in post-link as the element is already in
the DOM.
● It is possible to access the scope
● All child directives are linked so it’s safe to access them
○ their scope and the elements they affect.
● It is safe to attach events handlers to elements.
![Page 75: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/75.jpg)
Custom directives: pre-link,
● Use of pre-link is scarce,
○ A child needs data from its parent
● Safe to attach an event to the DOM element
○ Not safe to access DOM elements from child directives
● The scope is not linked yet.
![Page 76: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/76.jpg)
Custom directives: compile
● In this phase AngularJS manipulates the DOM of the HTML template
● Each directive has a chance to do some processing for all and each DOM
nodes it appears in.
● The scope is not attached yet.
● The template is still bare, without binding nor substitutions.
![Page 77: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/77.jpg)
THANKS FOR YOUR ATTENTIONLeave your questions on the comments section
![Page 78: Workshop 13: AngularJS Parte II](https://reader031.vdocuments.site/reader031/viewer/2022021813/587a16921a28abb4238b5471/html5/thumbnails/78.jpg)