Improve this Doc View Source

## Overview

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.) See also the Scopes guide for an in-depth introduction and usage examples.

## Inheritance

A scope can inherit from a parent scope, as in this example:

    var parent = $rootScope;
    var child = parent.$new();

    parent.salutation = "Hello";
    expect(child.salutation).toEqual('Hello');

    child.salutation = "Welcome";
    expect(child.salutation).toEqual('Welcome');
    expect(parent.salutation).toEqual('Hello');

When interacting with `Scope` in tests, additional helper methods are available on the instances of `Scope` type. See ngMock Scope for additional details.

## Usage

`$rootScope.Scope([providers], [instanceCache]);`

### Arguments

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 `providers`. This is handy when unit-testing and having the need to override a default service.

### Returns

Object | Newly created scope.

## Methods

- ###

  `$new(isolate, parent);`

  Creates a new child scope.

  The parent scope will propagate the $digest() event. 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.

  #### Parameters

  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.
  parent (optional) | Scope | The `Scope` that will be the `$parent` of the newly created scope. Defaults to `this` scope if not provided. This is used when creating a transclude scope to correctly place it in the scope hierarchy while maintaining the correct prototypical inheritance. (default: this)

  #### Returns

  Object | The newly created child scope.

- ###

  `$watch(watchExpression, listener, [objectEquality]);`

  Registers a `listener` callback to be executed whenever the `watchExpression` changes.

  - The `watchExpression` is called on every call to $digest() and should return the value that will be watched. (`watchExpression` should not change its value when executed multiple times with the same input because it may be executed multiple times by $digest(). That is, `watchExpression` should be idempotent.)
  - The `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). Inequality is determined according to reference inequality, strict comparison via the `!==` Javascript operator, unless `objectEquality == true` (see next point)
  - When `objectEquality == true`, inequality of the `watchExpression` is determined according to the `angular.equals` function. To save the value of the object for later comparison, the `angular.copy` function is used. This therefore means that watching complex objects will have adverse memory and performance implications.
  - This should not be used to watch for changes in objects that are or contain File objects due to limitations with `angular.copy`.
  - The watch `listener` may change the model, which may trigger other `listener`s 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`. (Be prepared for multiple calls to your `watchExpression` because it will execute multiple times in a single $digest cycle if a change is detected.)

  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.

  #### Parameters

  Param | Type | Details
  --- | --- | ---

  watchExpression

  function()string

  Expression that is evaluated on each $digest cycle. A change in the return value triggers a call to the `listener`.
  - `string`: Evaluated as expression
  - `function(scope)`: called with current `scope` as a parameter.

  listener

  function(newVal, oldVal, scope)

  Callback called whenever the value of `watchExpression` changes.
  - `newVal` contains the current value of the `watchExpression`
  - `oldVal` contains the previous value of the `watchExpression`
  - `scope` refers to the current scope

  objectEquality (optional) | boolean | Compare for object equality using `angular.equals` instead of comparing for reference equality. (default: false)

  #### Returns

  function() | Returns a deregistration function for this listener.

  #### Example

      // 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();
      // the listener is always called during the first $digest loop after it was registered
      expect(scope.counter).toEqual(1);

      scope.$digest();
      // but now it will not be called unless the value changes
      expect(scope.counter).toEqual(1);

      scope.name = 'adam';
      scope.$digest();
      expect(scope.counter).toEqual(2);

      // Using a function as a watchExpression
      var food;
      scope.foodCounter = 0;
      expect(scope.foodCounter).toEqual(0);
      scope.$watch(
        // This function returns the value being watched. It is called for each turn of the $digest loop
        function() { return food; },
        // This is the change listener, called when the value returned from the above function changes
        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);

- ###

  `$watchGroup(watchExpressions, listener);`

  A variant of $watch() where it watches an array of `watchExpressions`. If any one expression in the collection changes the `listener` is executed.

  - The items in the `watchExpressions` array are observed via the standard `$watch` operation. Their return values are examined for changes on every call to `$digest`.
  - The `listener` is called whenever any expression in the `watchExpressions` array changes.

  `$watchGroup` is more performant than watching each expression individually, and should be used when the listener does not need to know which expression has changed. If the listener needs to know which expression has changed, $watch() or $watchCollection() should be used.

  #### Parameters

  Param | Type | Details
  --- | --- | ---
  watchExpressions | Array.<string|Function(scope)> | Array of expressions that will be individually watched using $watch()

  listener

  function(newValues, oldValues, scope)

  Callback called whenever the return value of any expression in `watchExpressions` changes The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching those of `watchExpression` and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching those of `watchExpression`.

  Note that `newValues` and `oldValues` reflect the differences in each individual expression, and not the difference of the values between each call of the listener. That means the difference between `newValues` and `oldValues` cannot be used to determine which expression has changed / remained stable:

      $scope.$watchGroup(['v1', 'v2'], function(newValues, oldValues) {
        console.log(newValues, oldValues);
      });

      // newValues, oldValues initially
      // [undefined, undefined], [undefined, undefined]

      $scope.v1 = 'a';
      $scope.v2 = 'a';

      // ['a', 'a'], [undefined, undefined]

      $scope.v2 = 'b'

      // v1 hasn't changed since it became `'a'`, therefore its oldValue is still `undefined`
      // ['a', 'b'], [undefined, 'a']

  The `scope` refers to the current scope.

  #### Returns

  function() | Returns a de-registration function for all listeners.

- ###

  `$watchCollection(obj, 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.

  - The `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.
  - The `listener` is called whenever anything within the `obj` has changed. Examples include adding, removing, and moving items belonging to an object or array.

  #### Parameters

  Param | Type | Details
  --- | --- | ---
  obj | string function(scope) | Evaluated as expression. The expression value should evaluate to an object or an array which is observed on each $digest cycle. Any shallow change within the collection will trigger a call to the `listener`.

  listener

  function(newCollection, oldCollection, scope)

  a callback function called when a change is detected.
  - The `newCollection` object is the newly modified data obtained from the `obj` expression
  - The `oldCollection` object is a copy of the former collection data. Due to performance considerations, the`oldCollection` value is computed only if the `listener` function declares two or more arguments.
  - The `scope` argument refers to the current scope.

  #### Returns

  function() | Returns a de-registration function for this listener. When the de-registration function is executed, the internal watch operation is terminated.

  #### Example

      $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);

- ###

  `$digest();`

  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 directive), 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.

  #### Example

      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();
      // the listener is always called during the first $digest loop after it was registered
      expect(scope.counter).toEqual(1);

      scope.$digest();
      // but now it will not be called unless the value changes
      expect(scope.counter).toEqual(1);

      scope.name = 'adam';
      scope.$digest();
      expect(scope.counter).toEqual(2);

- ###

  `$suspend();`

  Suspend watchers of this scope subtree so that they will not be invoked during digest.

  This can be used to optimize your application when you know that running those watchers is redundant.

  Warning

  Suspending scopes from the digest cycle can have unwanted and difficult to debug results. Only use this approach if you are confident that you know what you are doing and have ample tests to ensure that bindings get updated as you expect.

  Some of the things to consider are:

  - Any external event on a directive/component will not trigger a digest while the hosting scope is suspended - even if the event handler calls `$apply()` or `$rootScope.$digest()`.
  - Transcluded content exists on a scope that inherits from outside a directive but exists as a child of the directive's containing scope. If the containing scope is suspended the transcluded scope will also be suspended, even if the scope from which the transcluded scope inherits is not suspended.
  - Multiple directives trying to manage the suspended status of a scope can confuse each other:
    - A call to `$suspend()` on an already suspended scope is a no-op.
    - A call to `$resume()` on a non-suspended scope is a no-op.
    - If two directives suspend a scope, then one of them resumes the scope, the scope will no longer be suspended. This could result in the other directive believing a scope to be suspended when it is not.
  - If a parent scope is suspended then all its descendants will be also excluded from future digests whether or not they have been suspended themselves. Note that this also applies to isolate child scopes.
  - Calling `$digest()` directly on a descendant of a suspended scope will still run the watchers for that scope and its descendants. When digesting we only check whether the current scope is locally suspended, rather than checking whether it has a suspended ancestor.
  - Calling `$resume()` on a scope that has a suspended ancestor will not cause the scope to be included in future digests until all its ancestors have been resumed.
  - Resolved promises, e.g. from explicit `$q` deferreds and `$http` calls, trigger `$apply()` against the `$rootScope` and so will still trigger a global digest even if the promise was initiated by a component that lives on a suspended scope.

- ###

  `$isSuspended();`

  Call this method to determine if this scope has been explicitly suspended. It will not tell you whether an ancestor has been suspended. To determine if this scope will be excluded from a digest triggered at the $rootScope, for example, you must check all its ancestors:

      function isExcludedFromDigest(scope) {
      while(scope) {
        if (scope.$isSuspended()) return true;
        scope = scope.$parent;
      }
      return false;

  Be aware that a scope may not be included in digests if it has a suspended ancestor, even if `$isSuspended()` returns false.

  #### Returns

  | true if the current scope has been suspended.

- ###

  `$resume();`

  Resume watchers of this scope subtree in case it was suspended.

  See `$rootScope.Scope` for information about the dangers of using this approach.

- ###

  `$destroy();`

  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.

- ###

  `$eval([expression], [locals]);`

  Executes the `expression` on the current scope and returns the result. Any exceptions in the expression are propagated (uncaught). This is useful when evaluating AngularJS expressions.

  #### Parameters

  Param | Type | Details
  --- | --- | ---

  expression
  (optional)

  string function()

  An AngularJS expression to be executed.
  - `string`: execute using the rules as defined in expression.
  - `function(scope)`: execute the function with the current `scope` parameter.

  locals (optional) | object | Local variables object, useful for overriding values in scope.

  #### Returns

  * | The result of evaluating the expression.

  #### Example

      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);

- ###

  `$evalAsync([expression], [locals]);`

  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:

  - it will execute after the function that scheduled the evaluation (preferably before DOM rendering).
  - at least one $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`.

  #### Parameters

  Param | Type | Details
  --- | --- | ---

  expression
  (optional)

  string function()

  An AngularJS expression to be executed.
  - `string`: execute using the rules as defined in expression.
  - `function(scope)`: execute the function with the current `scope` parameter.

  locals (optional) | object | Local variables object, useful for overriding values in scope.

- ###

  `$apply([exp]);`

  `$apply()` is used to execute an expression in AngularJS from outside of the AngularJS framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). Because we are calling into the AngularJS framework we need to perform proper scope life cycle of exception handling, executing watches.

  Life cycle: Pseudo-Code of `$apply()`

      function $apply(expr) {
        try {
          return $eval(expr);
        } catch (e) {
          $exceptionHandler(e);
        } finally {
          $root.$digest();
        }
      }

  Scope's `$apply()` method transitions through the following stages:

  1. The expression is executed using the $eval() method.
  2. Any exceptions from the execution of the expression are forwarded to the $exceptionHandler service.
  3. The watch listeners are fired immediately after the expression was executed using the $digest() method.

  #### Parameters

  Param | Type | Details
  --- | --- | ---

  exp
  (optional)

  string function()

  An AngularJS expression to be executed.
  - `string`: execute using the rules as defined in expression.
  - `function(scope)`: execute the function with current `scope` parameter.

  #### Returns

  * | The result of evaluating the expression.

- ###

  `$applyAsync([exp]);`

  Schedule the invocation of $apply to occur at a later time. The actual time difference varies across browsers, but is typically around ~10 milliseconds.

  This can be used to queue up multiple expressions which need to be evaluated in the same digest.

  #### Parameters

  Param | Type | Details
  --- | --- | ---

  exp
  (optional)

  string function()

  An AngularJS expression to be executed.
  - `string`: execute using the rules as defined in expression.
  - `function(scope)`: execute the function with current `scope` parameter.

- ###

  `$on(name, listener);`

  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 scope that is currently handling the event. Once the event propagates through the scope hierarchy, this property is set to null.
  - `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.

  #### Parameters

  Param | Type | Details
  --- | --- | ---
  name | string | Event name to listen on.
  listener | function(event, ...args) | Function to call when the event is emitted.

  #### Returns

  function() | Returns a deregistration function for this listener.

- ###

  `$emit(name, args);`

  Dispatches an event `name` upwards through the scope hierarchy notifying the registered `$rootScope.Scope` 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.

  #### Parameters

  Param | Type | Details
  --- | --- | ---
  name | string | Event name to emit.
  args | * | Optional one or more arguments which will be passed onto the event listeners.

  #### Returns

  Object | Event object (see `$rootScope.Scope`).

- ###

  `$broadcast(name, args);`

  Dispatches an event `name` downwards to all child scopes (and their children) notifying the registered `$rootScope.Scope` 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.

  #### Parameters

  Param | Type | Details
  --- | --- | ---
  name | string | Event name to broadcast.
  args | * | Optional one or more arguments which will be passed onto the event listeners.

  #### Returns

  Object | Event object, see `$rootScope.Scope`

## Events

- ### $destroy

  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.

  #### Type:

  broadcast

  #### Target:

  scope being destroyed

## Properties

- ### `$id`

  | Unique scope ID (monotonically increasing) useful for debugging.

- ### `$parent`

  | Reference to the parent scope.

- ### `$root`

  | Reference to the root scope.