Scope
ng
A root scope can be retrieved using the $rootScope key from the
$injector. Child scopes are created using the
$new() method. (Most scopes are created automatically when
compiled HTML template is executed.)
Here is a simple scope snippet to show how you can interact with the scope.
var scope = $rootScope.$new();
scope.salutation = 'Hello';
scope.name = 'World';
expect(scope.greeting).toEqual(undefined);
scope.$watch('name', function() {
scope.greeting = scope.salutation + ' ' + scope.name + '!';
}); // initialize the watch
expect(scope.greeting).toEqual(undefined);
scope.name = 'Misko';
// still old value, since watches have not been called yet
expect(scope.greeting).toEqual(undefined);
scope.$digest(); // fire all the watches
expect(scope.greeting).toEqual('Hello Misko!');
A scope can inherit from a parent scope, as in this example:
var parent = $rootScope;
var child = parent.$new();
parent.salutation = "Hello";
child.name = "World";
expect(child.salutation).toEqual('Hello');
child.salutation = "Welcome";
expect(child.salutation).toEqual('Welcome');
expect(parent.salutation).toEqual('Hello');
Scope([providers][, instanceCache]);
| Param | Type | Details |
|---|---|---|
| providers (optional) | Object.<string, function()> | Map of service factory which need to be provided for the current scope. Defaults to ng. |
| instanceCache (optional) | Object.<string, *> | Provides pre-instantiated services which should
append/override services provided by |
| Object | Newly created scope. |
$apply() is used to execute an expression in angular from outside of the angular
framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).
Because we are calling into the angular framework we need to perform proper scope life
cycle of exception handling,
executing watches.
$apply()
function $apply(expr) {
try {
return $eval(expr);
} catch (e) {
$exceptionHandler(e);
} finally {
$root.$digest();
}
}
Scope's $apply() method transitions through the following stages:
$eval() method.$exceptionHandler service.watch listeners are fired immediately after the
expression was executed using the $digest() method.| Param | Type | Details |
|---|---|---|
| exp (optional) | stringfunction() | An angular expression to be executed.
|
| * | The result of evaluating the expression. |
Dispatches an event name downwards to all child scopes (and their children) notifying the
registered ng.$rootScope.Scope#methods_$on listeners.
The event life cycle starts at the scope on which $broadcast was called. All
listeners listening for name event on this scope get
notified. Afterwards, the event propagates to all direct and indirect scopes of the current
scope and calls all registered listeners along the way. The event cannot be canceled.
Any exception emitted from the listeners will be passed
onto the $exceptionHandler service.
| Param | Type | Details |
|---|---|---|
| name | string | Event name to broadcast. |
| args | ...* | Optional set of arguments which will be passed onto the event listeners. |
| Object | Event object, see |
Removes the current scope (and all of its children) from the parent scope. Removal implies
that calls to $digest() will no longer
propagate to the current scope and its children. Removal also implies that the current
scope is eligible for garbage collection.
The $destroy() is usually used by directives such as
ngRepeat for managing the
unrolling of the loop.
Just before a scope is destroyed, a $destroy event is broadcasted on this scope.
Application code can register a $destroy event handler that will give it a chance to
perform any necessary cleanup.
Note that, in AngularJS, there is also a $destroy jQuery event, which can be used to
clean up DOM bindings before an element is removed from the DOM.
Processes all of the watchers of the current scope and
its children. Because a watcher's listener can change
the model, the $digest() keeps calling the watchers
until no more listeners are firing. This means that it is possible to get into an infinite
loop. This function will throw 'Maximum iteration limit exceeded.' if the number of
iterations exceeds 10.
Usually, you don't call $digest() directly in
controllers or in
directives.
Instead, you should call $apply() (typically from within
a directives), which will force a $digest().
If you want to be notified whenever $digest() is called,
you can register a watchExpression function with
$watch() with no listener.
In unit tests, you may need to call $digest() to simulate the scope life cycle.
var scope = ...;
scope.name = 'misko';
scope.counter = 0;
expect(scope.counter).toEqual(0);
scope.$watch('name', function(newValue, oldValue) {
scope.counter = scope.counter + 1;
});
expect(scope.counter).toEqual(0);
scope.$digest();
// no variable change
expect(scope.counter).toEqual(0);
scope.name = 'adam';
scope.$digest();
expect(scope.counter).toEqual(1);
Dispatches an event name upwards through the scope hierarchy notifying the
registered ng.$rootScope.Scope#methods_$on listeners.
The event life cycle starts at the scope on which $emit was called. All
listeners listening for name event on this scope get
notified. Afterwards, the event traverses upwards toward the root scope and calls all
registered listeners along the way. The event will stop propagating if one of the listeners
cancels it.
Any exception emitted from the listeners will be passed
onto the $exceptionHandler service.
| Param | Type | Details |
|---|---|---|
| name | string | Event name to emit. |
| args | ...* | Optional set of arguments which will be passed onto the event listeners. |
| Object | Event object (see |
Executes the expression on the current scope and returns the result. Any exceptions in
the expression are propagated (uncaught). This is useful when evaluating Angular
expressions.
var scope = ng.$rootScope.Scope();
scope.a = 1;
scope.b = 2;
expect(scope.$eval('a+b')).toEqual(3);
expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
| Param | Type | Details |
|---|---|---|
| expression (optional) | stringfunction() | An angular expression to be executed.
|
| locals (optional) | object | Local variables object, useful for overriding values in scope. |
| * | The result of evaluating the expression. |
Executes the expression on the current scope at a later point in time.
The $evalAsync makes no guarantees as to when the expression will be executed, only
that:
$digest cycle will be performed after
expression execution.Any exceptions from the execution of the expression are forwarded to the
$exceptionHandler service.
Note: if this function is called outside of a $digest cycle, a new $digest cycle
will be scheduled. However, it is encouraged to always call code that changes the model
from within an $apply call. That includes code evaluated via $evalAsync.
| Param | Type | Details |
|---|---|---|
| expression (optional) | stringfunction() | An angular expression to be executed.
|
Creates a new child scope.
The parent scope will propagate the $digest() and
$digest() events. The scope can be removed from the
scope hierarchy using $destroy().
$destroy() must be called on a scope when it is
desired for the scope and its child scopes to be permanently detached from the parent and
thus stop participating in model change detection and listener notification by invoking.
| Param | Type | Details |
|---|---|---|
| isolate | boolean | If true, then the scope does not prototypically inherit from the parent scope. The scope is isolated, as it can not see parent scope properties. When creating widgets, it is useful for the widget to not accidentally read parent state. |
| Object | The newly created child scope. |
Listens on events of a given type. See $emit for
discussion of event life cycle.
The event listener function format is: function(event, args...). The event object
passed into the listener has the following attributes:
targetScope - {Scope}: the scope on which the event was $emit-ed or
$broadcast-ed.currentScope - {Scope}: the current scope which is handling the event.name - {string}: name of the event.stopPropagation - {function=}: calling stopPropagation function will cancel
further event propagation (available only for events that were $emit-ed).preventDefault - {function}: calling preventDefault sets defaultPrevented flag
to true.defaultPrevented - {boolean}: true if preventDefault was called.| Param | Type | Details |
|---|---|---|
| name | string | Event name to listen on. |
| listener | function(event, args... | Function to call when the event is emitted. |
| function() | Returns a deregistration function for this listener. |
Registers a listener callback to be executed whenever the watchExpression changes.
watchExpression is called on every call to $digest() and should return the value that will be watched. (Since
$digest() reruns when it detects changes the
watchExpression can execute multiple times per
$digest() and should be idempotent.)listener is called only when the value from the current watchExpression and the
previous call to watchExpression are not equal (with the exception of the initial run,
see below). The inequality is determined according to
angular.equals function. To save the value of the object for later comparison,
the angular.copy function is used. It also means that watching complex options
will have adverse memory and performance implications.listener may change the model, which may trigger other listeners to fire.
This is achieved by rerunning the watchers until no changes are detected. The rerun
iteration limit is 10 to prevent an infinite loop deadlock.If you want to be notified whenever $digest is called,
you can register a watchExpression function with no listener. (Since watchExpression
can execute multiple times per $digest cycle when a
change is detected, be prepared for multiple calls to your listener.)
After a watcher is registered with the scope, the listener fn is called asynchronously
(via $evalAsync) to initialize the
watcher. In rare cases, this is undesirable because the listener is called when the result
of watchExpression didn't change. To detect this scenario within the listener fn, you
can compare the newVal and oldVal. If these two values are identical (===) then the
listener was called due to initialization.
The example below contains an illustration of using a function as your $watch listener
// let's assume that scope was dependency injected as the $rootScope
var scope = $rootScope;
scope.name = 'misko';
scope.counter = 0;
expect(scope.counter).toEqual(0);
scope.$watch('name', function(newValue, oldValue) {
scope.counter = scope.counter + 1;
});
expect(scope.counter).toEqual(0);
scope.$digest();
// no variable change
expect(scope.counter).toEqual(0);
scope.name = 'adam';
scope.$digest();
expect(scope.counter).toEqual(1);
// Using a listener function
var food;
scope.foodCounter = 0;
expect(scope.foodCounter).toEqual(0);
scope.$watch(
// This is the listener function
function() { return food; },
// This is the change handler
function(newValue, oldValue) {
if ( newValue !== oldValue ) {
// Only increment the counter if the value changed
scope.foodCounter = scope.foodCounter + 1;
}
}
);
// No digest has been run so the counter will be zero
expect(scope.foodCounter).toEqual(0);
// Run the digest but since food has not changed count will still be zero
scope.$digest();
expect(scope.foodCounter).toEqual(0);
// Update food and run digest. Now the counter will increment
food = 'cheeseburger';
scope.$digest();
expect(scope.foodCounter).toEqual(1);
| Param | Type | Details |
|---|---|---|
| watchExpression | function()string | Expression that is evaluated on each
|
| listener (optional) | function()string | Callback called whenever the return value of
the
|
| objectEquality (optional) | boolean | Compare object for equality rather than for reference. |
| function() | Returns a deregistration function for this listener. |
Shallow watches the properties of an object and fires whenever any of the properties change
(for arrays, this implies watching the array items; for object maps, this implies watching
the properties). If a change is detected, the listener callback is fired.
obj collection is observed via standard $watch operation and is examined on every
call to $digest() to see if any items have been added, removed, or moved.listener is called whenever anything within the obj has changed. Examples include
adding, removing, and moving items belonging to an object or array.
$scope.names = ['igor', 'matias', 'misko', 'james'];
$scope.dataCount = 4;
$scope.$watchCollection('names', function(newNames, oldNames) {
$scope.dataCount = newNames.length;
});
expect($scope.dataCount).toEqual(4);
$scope.$digest();
//still at 4 ... no changes
expect($scope.dataCount).toEqual(4);
$scope.names.pop();
$scope.$digest();
//now there's been a change
expect($scope.dataCount).toEqual(3);
| Param | Type | Details |
|---|---|---|
| obj | stringFunction(scope | Evaluated as expression. The
expression value should evaluate to an object or an array which is observed on each
|
| listener | function(newCollection, oldCollection, scope | a callback function that is
fired with both the |
| function() | Returns a de-registration function for this listener. When the de-registration function is executed, the internal watch operation is terminated. |
| number | Unique scope ID (monotonically increasing alphanumeric sequence) useful for debugging. |
Broadcasted when a scope and its children are being destroyed.
Note that, in AngularJS, there is also a $destroy jQuery event, which can be used to
clean up DOM bindings before an element is removed from the DOM.