3. Overview: Scopes
What's scopes?
• The source of truth for application state
• Execution context for expression
• Map mimics DOM structure
• Agency to watch expression and propagate events
4. Overview: Scopes
Scopes' main features:
• Observe model mutations ($watch)
• Propagate model changes to whole application ($apply)
• Can be nested to limit access from other components
• Provide execution environment to evaluate expressions
E.g: {{2 + 3}}
5. Overview: Scope
$rootScope and $scope
• $rootScope: global context in Angular apps
Parents of all $scope object, initialize with Angular application
<div ng-app="App"></div>
• $scope: peculiar data model object
Connection between controller and view
angular.module('App', []).controller('AppController', function($scope) {...});
angular.module('App', []).directive('myDirective', function(){
return {
controller: function($scope) { ... },
link: function(scope, element, attr) { ... }
}
});
6. Overview: Scope
Scope life cycle
• Creation
• Watcher registration
• Model mutation
• Mutation observation
• Destruction
7. Javascript prototypal inheritance
function Human(name) {
this.name = name;
}
Human.prototype.say = function() {
console.log('I am an' + this.name);
}
var myDad = new Human('Billionaire');
myDad.money = 1000000;
myDad.cars = ['BMW X6', 'RR Phantom', 'Maybach'];
myDad.houses = {hanoi: 200, saigon: 500};
var me = Object.create(myDad);
me.money = -50000;
me.cars[1] = "Honda Super Dream";
me.houses.hanoi = 100;
Human
myDad
Cars: ['BMW X6', 'RR Phantom','Maybach']
Money: 1000000
houses: {hanoi: 200, saigon: 500}
me Money: -50000
8. Javascript prototypal inheritance
• To find a property in child object
• Searching in child object
• Not found -> looking in inherited object
• New properties of child object will hide/shadows parent property with the same
name
• If objects are found in parent, the property will be updated on original object
9. Angular scope inheritance
Normal prototypal scope inheritance in AngularJS
• Ng-controller
• Ng-include
• Ng-switch
• Directive with scope: true
10. Angular scope inheritance
Ng-repeat
• Normal prototypal inheritance with copy/assignment
• Each iteration create new child scope
• Child scopes get new properties
childScope = scope.$new(); // child scope prototypically inherits from parent scope ...
childScope[valueIdent] = value; // creates a new childScope property
11. Angular scope inheritance
Directive - isolated scope (scope: {...})
• Not prototypal inheritance
• Various option to access parent scopes through attributes:
• '=': two-way data binding
• '@': one-way data binding
• '&': bind to parent expression
12. Angular scope inheritance
Directive - transcluded scope (transcluded: true)
• Beside of isolated scope, new transcluded scope is
created
• New transcluded scope is inherited from parent scope
• Avoid child scope hiding/shadowing parent scope's
properties
• Both isolated scope and transcluded scope can
access to parent scope through $parent
Nested scopes are either "child scopes" or "isolate scopes".
A "child scope" (prototypically) inherits properties from its parent scope. An "isolate scope" does not
Peculiar : normal data model -> gatekeeper of data, responsible for handling and manipulating data
1. The root scope is created during the application bootstrap by the $injector. During template linking, some directives create new child scopes.
2. During template linking, directives register watches on the scope. These watches will be used to propagate model values to the DOM.
3. For mutations to be properly observed, you should make them only within the scope.$apply(). Angular APIs do this implicitly, so no extra $apply call is needed when doing synchronous work in controllers, or asynchronous work with $http, $timeout or $interval services.
4. At the end of $apply, Angular performs a $digest cycle on the root scope, which then propagates throughout all child scopes. During the $digest cycle, all $watched expressions or functions are checked for model mutation and if a mutation is detected, the $watch listener is called.
5. When child scopes are no longer needed, it is the responsibility of the child scope creator to destroy them via scope.$destroy() API. This will stop propagation of $digest calls into the child scope and allow for memory used by the child scope models to be reclaimed by the garbage collector.
For each item/iteration,
ng-repeat creates a new scope, which prototypically inherits from the parent scope, but it also assigns the item's value to a new property on the new child scope.
since the directive cannot accidentally read or modify the parent scope.
<my-directive interpolated="{{parentProp1}}" twowayBinding="parentProp2">
scope: { interpolatedProp: '@interpolated', twowayBindingProp: '=twowayBinding' }
So if your transcluded content (i.e., the stuff that ng-transclude will be replaced with) requires 2-way data binding to a primitive in the parent scope