Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Front End Workshops
XII. AngularJS - Part 3
Juan Luís Marí
jlmari@visual-engin.com
Pablo Balduz
pbalduz@visual-engin.com
H...
Overview
“AngularJS is turn-based”
In previous chapters...
● AngularJS intro
● Modules and dependency injection
● Filters, Controllers and Services
● Routes
...
Overview
● Scope functions
● Patterns
● Testing
● Directives functions (continuation of custom directives)
○ compile, cont...
Scope functions
— Watch, apply & Digest—
Scope functions
Watch, apply and digest are $scope functions used to monitor and process
binded data in terms of the diges...
Scope functions - watch
Data binding creates ‘watchers’ internally. Every digest cycle will check
watched variables for ch...
Scope functions - apply
Through the digest cycle, watched variables will be monitored.
But sometimes we don’t have a varia...
Scope functions - apply
function Ctrl($scope) {
$scope.message = "Waiting 2000ms for update";
setTimeout(function () {
$sc...
Scope functions - apply
When to use apply:
● Very rarely ( or better NEVER ). Two well-know cases:
○ dealing with sockets
...
Scope functions - digest
$scope.digest triggers a digest cycle, but we should never call it directly.
● digest is triggere...
Common Patterns
— non trivial only—
Known patterns
Angular is already build as a collection of patterns
● Services are singletons.
● Factories are factories.
...
Observer (publish-subscribe)
Observers are similar to watchers, but instead of permanently watch a fuction
they subscribe ...
Event listener (View observer)
Multiple build-in directives are event listeners:
● ng-click, ng-dbl-click
● ng-mouse…
● ng...
Event listener example
angular.module('myApp', [])
.directive('myDirective', function myDirective () {
return {
restrict: ...
Other patterns
Proxy
● a service using $http or $resource (Restful http) internally.
Data Mapper
● a service returning Mod...
Testing
— AngularJS embraces testing—
AngularJS takes well care of testing:
● Well supported by Karma (test runner)
● Can use Mocha, Sinon, Chai ...
● Protracto...
E2E framework based on Jasmine and Selenium’s WebDriver
Ability to simulate user interaction
Simulation in selenium and mo...
Provides several services to mock Angular behaviour:
● $timeout,
● $controller : inject controllers
● $httpBackend: patch ...
Unit Testing
● Testing individual, small units of code → Need of isolated code
○ Note: Bad isolated code may force the app...
Dependency Injection
● AngularJS built-in. Allows to pass in a
component's dependencies and stub or mock
them as you wish....
$httpBackend
● angular-mocks module allows to inject and mock the AngularJS services, so they can be extended
and used syn...
Custom directives - Continuation
— DOM Manipulation—
There are 3 types of functions, by order of execution:
○ compile, controller and link
● Compile happens once, before the t...
compile: function CompilingFunction($templateElement, $templateAttributes) {
…}
link: function LinkingFunction($scope, $el...
Custom directives: link, prelink, postlink
● There are 4 arguments available for these functions (in this order)
○ scope, ...
Custom directives: link, prelink, postlink
var app = angular.module('app', []);
app.directive('dad', function () {
return ...
Custom directives: post-link,
● It is safe to manipulate the DOM in post-link as the element is already in
the DOM.
● It i...
Custom directives: pre-link,
● Use of pre-link is scarce,
○ A child needs data from its parent
● Safe to attach an event t...
Custom directives: compile
● In this phase AngularJS manipulates the DOM of the HTML template
● Each directive has a chanc...
Built-in directives
Built-in directives
● ng-model
● ng-src
● ng-class
● ng-style
● ng-click
● ng-if
● ng-show
● ng-include
● ng-repeat
ng-model
● Binds inputs to scope properties
● If property does not exist, it is created and added to the scope
● Watches m...
ng-src
● src leads to problems when evaluating expressions
● Prevents browser from loading resources before an expression ...
ng-class
● Allows to dynamically set CSS classes on an HTML
● Ways of operating (syntax):
○ String
○ Key-value pair object...
ng-class
String syntax
Array syntax
Key-value pair syntax
<input type="text" ng-model="style">
<div ng-class="style">Strin...
ng-class
Ternary operator
Specific numbers
ngClass as a class
ngClass as an attribute (every example shown except the last...
ng-style
● Allows setting style on an HTML conditionally
● Interpolates javascript object into style attribute, not css cl...
ng-click
● Specify custom behavior when an element is clicked
<button ng-click="count = 0">
Reset
</button>
<button ng-cli...
ng-show
● Shows / hides HTML element based on an expression
● Adds / removes ng-hide class
● Animations
Element visible wh...
ng-if
● Removes / recreates part of the DOM
● scope is removed and recreated
● ng-model with ng-if issues
● Animations
Sim...
ngAnimate
● Include angular-animate.js and load module
● Directives support
○ ngRepeat
○ ngShow
○ ngHide
○ ngIf
○ ...
● CS...
ngAnimate
CSS based animations
● No need of JavaScript code at all
● CSS class referenced between HTML and CSS
● 2 css cla...
ngAnimate
CSS based animations
● Staggering animations
● ng-Animate css class
● Custom keyframe animations
.zipper.ng-anim...
ngAnimate
JS based animations
Register JavaScript animation on the module
<div ng-repeat="item in items" class="slide">
{{...
ngAnimate
ngAnimate documentation: https://docs.angularjs.org/api/ngAnimate
ng-include
● Add HTML code from external file to the current one
○ Fetches, compiles and includes an external HTML fragmen...
ng-include
● Cross-domain:
○ By default, the ng-include directive does not allow you to include
files from other domains.
...
ng-repeat
● Instantiates a template once per item from a collection
<div ng-repeat="item in collection"> ... </div>
● Each...
ng-repeat
ng-repeat
● Continuously watching if changes in the collection happens
○ Automatically changing DOM (when adding, removing...
Workshop 14: AngularJS Parte III
Upcoming SlideShare
Loading in …5
×

Workshop 14: AngularJS Parte III

Workshop AngularJS (3/3)
AngularJS y su testing.

Presentado por ingenieros: Héctor Canto, Juan Luís Marí y Pablo Balduz.

  • Login to see the comments

Workshop 14: AngularJS Parte III

  1. 1. Front End Workshops XII. AngularJS - Part 3 Juan Luís Marí jlmari@visual-engin.com Pablo Balduz pbalduz@visual-engin.com Héctor Canto hcanto@visual-engin.com
  2. 2. Overview “AngularJS is turn-based”
  3. 3. In previous chapters... ● AngularJS intro ● Modules and dependency injection ● Filters, Controllers and Services ● Routes ● Digest cycle ● Data binding ● Directives ...
  4. 4. Overview ● Scope functions ● Patterns ● Testing ● Directives functions (continuation of custom directives) ○ compile, controller and link functions ● Build-in directives
  5. 5. Scope functions — Watch, apply & Digest—
  6. 6. Scope functions Watch, apply and digest are $scope functions used to monitor and process binded data in terms of the digest cycle. There are used very scarcely but it is good to know in order to understand bad updates, performance issues and digest loop errors. http://tutorials.jenkov.com/angularjs/watch-digest-apply.html
  7. 7. Scope functions - watch Data binding creates ‘watchers’ internally. Every digest cycle will check watched variables for changes and react accordingly. Variables are watched implicitly when we use double curly brackets: {{myVar}} and explicitly: $scope.watch(‘myVar’, function(){...}); As 1st parameter we can call a function, also. The 2nd function is called a ‘listener’. http://tutorials.jenkov.com/angularjs/watch-digest-apply.html
  8. 8. Scope functions - apply Through the digest cycle, watched variables will be monitored. But sometimes we don’t have a variable to watch and we are waiting for an async event. Some directives and services already use apply for us internally. ● ng-click ● $timeout ● $http and explicitly: http://jimhoskins.com/2012/12/17/angularjs-and-apply.html
  9. 9. Scope functions - apply function Ctrl($scope) { $scope.message = "Waiting 2000ms for update"; setTimeout(function () { $scope.$apply(function () { $scope.message = "Timeout called!"; }); }, 2000); } Note: Instead, you could use $timeout.
  10. 10. Scope functions - apply When to use apply: ● Very rarely ( or better NEVER ). Two well-know cases: ○ dealing with sockets ○ wrapping non-Angular code ○ when you know a variable is initialized outside the digest cycle How to use apply: ● with a function preferably: $scope.apply( function() {}); ● Tip: Use $timeout without delay (but it will be defered). http://stackoverflow.com/questions/23070822/angular-scope-apply-vs-timeout-as-a-safe-apply
  11. 11. Scope functions - digest $scope.digest triggers a digest cycle, but we should never call it directly. ● digest is triggered internally ● after the execution of $scope.apply, at the end of its execution We use apply (and therefore digest) when we don’t have a variable to watch and we are waiting for an async event. http://jimhoskins.com/2012/12/17/angularjs-and-apply.html
  12. 12. Common Patterns — non trivial only—
  13. 13. Known patterns Angular is already build as a collection of patterns ● Services are singletons. ● Factories are factories. ● Data-binding and $scope.watch implements a watcher pattern. ● Controller and Template. ● Dependency injections: everywhere. http://blog.mgechev.com/2014/05/08/angularjs-in-patterns-part-1-overview-of-angularjs/
  14. 14. Observer (publish-subscribe) Observers are similar to watchers, but instead of permanently watch a fuction they subscribe to events. To subscribe: $scope.on(‘event-name’, function handler() { //your code here } And to launch the event: function ExampleCtrl($scope) { $scope.$emit('event-name', { foo: 'bar' }); //upwards on the scope hierarchy $scope.$broadcast('event-name', { foo: 'bar' }); //downwards to all child $rootScope.$broadcast('event-name', { foo: 'bar' }); //to everybody } http://blog.mgechev.com/2014/07/05/angularjs-in-patterns-part-3/
  15. 15. Event listener (View observer) Multiple build-in directives are event listeners: ● ng-click, ng-dbl-click ● ng-mouse… ● ng-keydown, ng-keyup ● ng-change You can add your own event listeners. Let see an example: http://tutorials.jenkov.com/angularjs/events.html
  16. 16. Event listener example angular.module('myApp', []) .directive('myDirective', function myDirective () { return { restrict: 'AE', link: myDirectiveLink } }); function myDirectiveLink (scope, element, attrs) { var domElement = element[0]; // Get the native JS element domElement.addEventListener("dragstart", myEventListener, false); // You can use ngDraggable but it uses jQuery } function myEventListener () { // Handle event here }
  17. 17. Other patterns Proxy ● a service using $http or $resource (Restful http) internally. Data Mapper ● a service returning Model instances calling $http or $resource.
  18. 18. Testing — AngularJS embraces testing—
  19. 19. AngularJS takes well care of testing: ● Well supported by Karma (test runner) ● Can use Mocha, Sinon, Chai ... ● Protractor and ngMock specially build for testing Angular. ● KEY: inject dependencies and mock key elements Testing in AngularJS https://www.smashingmagazine.com/2014/10/introduction-to-unit-testing-in-angularjs/ https://quickleft.com/blog/angularjs-unit-testing-for-real-though/
  20. 20. E2E framework based on Jasmine and Selenium’s WebDriver Ability to simulate user interaction Simulation in selenium and most browsers Usually, we will run tests in Selenium (without UI) and all target browsers. We can automate this with Gulp Protractor
  21. 21. Provides several services to mock Angular behaviour: ● $timeout, ● $controller : inject controllers ● $httpBackend: patch or mock $http calls ● module() and inject(): ○ resolve dependencies on tests ○ patch methods ○ mock scope ngMock http://www.bradoncode.com/blog/2015/05/27/ngmock-fundamentals-angularjs-testing-inject/
  22. 22. Unit Testing ● Testing individual, small units of code → Need of isolated code ○ Note: Bad isolated code may force the app to create related pieces as server’s requests or new DOM elements → Affect other tests and produce errors ● Solutions: Dependency Injection and Mocking Services ○ DOM elements abstracted → never directly modified ○ XHR requests and petitions → simulated (by dependency injection of $httpBackend) ■ All we really need is to verify whether a certain request has been sent or not, or alternatively just let the application make requests, respond with pre-trained responses and assert that the end result is what we expect it to be.
  23. 23. Dependency Injection ● AngularJS built-in. Allows to pass in a component's dependencies and stub or mock them as you wish. ● Does not modify any global variable, so it does not affect other tests angular.module('app', []) .controller(ExampleCtrl, function ExampleCtrl($scope) { ... }); describe('ExampleCtrl tests', function() { beforeEach(module('app')); var $controller; beforeEach(inject(function(_$controller_){ // The injector unwraps the underscores (_) from around the parameter names when matching $controller = _$controller_; })); describe('block to be tested', function() { it('test1', function() { // create a scope object for us to use. var $scope = {}; // now run that scope through the controller function, injecting any services or other injectables we need. // **NOTE**: this is the only time the controller function will be run, so anything that occurs inside of that will already be done before the first spec. var controller = $controller('ExampleController', { $scope: $scope }); }; }); });
  24. 24. $httpBackend ● angular-mocks module allows to inject and mock the AngularJS services, so they can be extended and used synchronously → $httpBackend is one of them ● Service in module ngMock ● Fake HTTP backend implementation suitable for unit testing applications that use the $http service. ● Allows not using external dependencies, so the requests to URLs are mocked. ● With dependency injection, it is easy to inject $httpBackend mock and use it to verify the requests and respond with some testing data without sending a request to a real server. ● $httpBackend.flush() allows to flush pending requests, so the test will run synchronous but preserving the async of the backend API
  25. 25. Custom directives - Continuation — DOM Manipulation—
  26. 26. 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/
  27. 27. compile: function CompilingFunction($templateElement, $templateAttributes) { …} link: function LinkingFunction($scope, $element, $attributes) { ... } …} link: { pre: function PreLinkingFunction($scope, $element, $attributes) { ... }, post: function PostLinkingFunction($scope, $element, $attributes) { ... }, } Custom directives: functions http://plnkr.co/edit/qrDMJBlnwdNlfBqEEXL2?p=preview https://github.com/angular/angular.js/wiki/Understanding-Directives
  28. 28. 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.
  29. 29. Custom directives: link, prelink, postlink var 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 Paul Hey, I am David, and my dad is Paul
  30. 30. 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.
  31. 31. 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.
  32. 32. 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.
  33. 33. Built-in directives
  34. 34. Built-in directives ● ng-model ● ng-src ● ng-class ● ng-style ● ng-click ● ng-if ● ng-show ● ng-include ● ng-repeat
  35. 35. ng-model ● Binds inputs to scope properties ● If property does not exist, it is created and added to the scope ● Watches model by reference Important! ● Allows animation and validation <script> angular.module("module", []) .controller("controller", ['$scope', function($scope) { $scope.value = "Luis"; }]); </script> <div ng-controller="controller"> Name: <input ng-model="value"/> </div>
  36. 36. ng-src ● src leads to problems when evaluating expressions ● Prevents browser from loading resources before an expression is evaluated Buggy way Correct way <img src="http://www.gravatar.com/avatar/{{hash}}" alt="Description"/> <img ng-src="http://www.gravatar.com/avatar/{{hash}}" alt="Description" />
  37. 37. ng-class ● Allows to dynamically set CSS classes on an HTML ● Ways of operating (syntax): ○ String ○ Key-value pair object ○ Array of strings (type 1) or objects (type 2) ○ Ternary operator ● Usage options: class and attribute
  38. 38. ng-class String syntax Array syntax Key-value pair syntax <input type="text" ng-model="style"> <div ng-class="style">String syntax</div> <input type="text" ng-model="styleOne"> <input type="text" ng-model="styleTwo"> <div ng-class="[styleOne, styleTwo]">Array syntax</div> <input type="checkbox" ng-model="great"> Barça <input type="checkbox" ng-model="poor"> Madrid <div ng-class="{ styleOne: great, styleTwo: poor }">
  39. 39. ng-class Ternary operator Specific numbers ngClass as a class ngClass as an attribute (every example shown except the last one) ng-class="variableToEvaluate ? 'class-if-true' : 'class-if-false'"> <ul><li ng-class="{ 'text-success': $first }" ng-repeat="item in items">{{ item.name }}</li></ul> <div class="item ng-class:type;">Stuff</div> <div class="item ng-class:[styleOne, styleTwo];">Stuff</div> <div class="item ng-class:{ 'text-error': wrong };">Stuff</div>
  40. 40. ng-style ● Allows setting style on an HTML conditionally ● Interpolates javascript object into style attribute, not css class Following directive will be translated to style=”color:red” Following directive will be translated to class=”color” For interpolation, instead of doing this: do this: ng-style="{color: 'red'}" ng-class="{color: colorClass}" style="width: {{progress}}" ng-style="{width: progress}"
  41. 41. ng-click ● Specify custom behavior when an element is clicked <button ng-click="count = 0"> Reset </button> <button ng-click="reset()"> Reset </button>
  42. 42. ng-show ● Shows / hides HTML element based on an expression ● Adds / removes ng-hide class ● Animations Element visible when $scope.value is truthy Element hidden when $scope.value is falsy <div ng-show="value"></div> <div ng-show="value" class="ng-hide"></div>
  43. 43. ng-if ● Removes / recreates part of the DOM ● scope is removed and recreated ● ng-model with ng-if issues ● Animations Similar usage to ngShow / ngHide <div ng-if="value"></div>
  44. 44. ngAnimate ● Include angular-animate.js and load module ● Directives support ○ ngRepeat ○ ngShow ○ ngHide ○ ngIf ○ ... ● CSS / JS based animations
  45. 45. ngAnimate CSS based animations ● No need of JavaScript code at all ● CSS class referenced between HTML and CSS ● 2 css classes added depending on the animation event <div ng-if="bool" class="fade"> Fade me in out </div> <button ng-click="bool=true">Fade In!</button> <button ng-click="bool=false">Fade Out!</button> .fade.ng-enter { transition:0.5s linear all; opacity:0; } .fade.ng-enter.ng-enter-active { opacity:1; }
  46. 46. ngAnimate CSS based animations ● Staggering animations ● ng-Animate css class ● Custom keyframe animations .zipper.ng-animate { transition:0.5s linear all; } .zipper.ng-enter { opacity:0; } .zipper.ng-enter.ng-enter-active { opacity:1; } .zipper.ng-leave { opacity:1; } .zipper.ng-leave.ng-leave-active { opacity:0; }
  47. 47. ngAnimate JS based animations Register JavaScript animation on the module <div ng-repeat="item in items" class="slide"> {{ item }} </div> myModule.animation('.slide', [function() { return { enter: function(element, doneFn) { // Do some cool animation and call doneFn }, move: function(element, doneFn) {}, leave: function(element, doneFn) {} } }]);
  48. 48. ngAnimate ngAnimate documentation: https://docs.angularjs.org/api/ngAnimate
  49. 49. ng-include ● Add HTML code from external file to the current one ○ Fetches, compiles and includes an external HTML fragment ● Create new scope for the included template ● The included HTML files can also contain AngularJS code <div ng-include="'myFile.html'"></div>
  50. 50. ng-include ● Cross-domain: ○ By default, the ng-include directive does not allow you to include files from other domains. ○ To include files from another domain, you can add a whitelist of legal files and/or domains in the config function of your application: var app = angular.module('myApp', []) app.config(function($sceDelegateProvider) { $sceDelegateProvider.resourceUrlWhitelist([ 'http://www.refsnesdata.no/**' ]); });
  51. 51. ng-repeat ● Instantiates a template once per item from a collection <div ng-repeat="item in collection"> ... </div> ● Each template instance gets its own scope ● It is also possible to get ngRepeat to iterate over the properties of an object ○ Note: The built-in filters orderBy and filter do not work with objects <div ng-repeat="(key, value) in myObj"> ... </div>
  52. 52. ng-repeat
  53. 53. ng-repeat ● Continuously watching if changes in the collection happens ○ Automatically changing DOM (when adding, removing or reordering items) ○ “Keep track” items with their DOM elements → Avoids re-render them if not needed ● Default tracking function (changeable with track-by) ○ Tracks by identity of item ○ Does not allows duplicated items ● ng-repeat in more than one parent element of the HTML ○ ng-repeat-start ○ ng-repeat-end range of the repeater

×