diff options
Diffstat (limited to 'docs/content/guide/dev_guide.scopes.internals.ngdoc')
| -rw-r--r-- | docs/content/guide/dev_guide.scopes.internals.ngdoc | 230 |
1 files changed, 0 insertions, 230 deletions
diff --git a/docs/content/guide/dev_guide.scopes.internals.ngdoc b/docs/content/guide/dev_guide.scopes.internals.ngdoc deleted file mode 100644 index 090d5261..00000000 --- a/docs/content/guide/dev_guide.scopes.internals.ngdoc +++ /dev/null @@ -1,230 +0,0 @@ -@ngdoc overview -@name Developer Guide: Scopes: Scope Internals -@description - -## What is a scope? - -A scope is an execution context for {@link dev_guide.expressions expressions}. You can think of a -scope as a JavaScript object that has an extra set of APIs for registering change listeners and for -managing its own life cycle. In Angular's implementation of the model-view-controller design -pattern, a scope's properties comprise both the model and the controller methods. - - -### Scope characteristics -- Scopes provide APIs ({@link api/angular.module.ng.$rootScope.Scope#$watch $watch}) to observe model mutations. -- Scopes provide APIs ({@link api/angular.module.ng.$rootScope.Scope#$apply $apply}) to propagate any model changes -through the system into the view from outside of the "Angular realm" (controllers, services, -Angular event handlers). -- Scopes can be nested to isolate application components while providing access to shared model -properties. A scope (prototypically) inherits properties from its parent scope. -- In some parts of the system (such as controllers, services and directives), the scope is made -available as `this` within the given context. (Note: This api will change before 1.0 is released.) - - -### Root scope - -Every application has a root scope, which is the ancestor of all other scopes. - -### What is scope used for? - -{@link dev_guide.expressions Expressions} in the view are {@link api/angular.module.ng.$rootScope.Scope#$eval evaluated} -against the current scope. When HTML DOM elements are attached to a scope, expressions in those -elements are evaluated against the attached scope. - -There are two kinds of expressions: - -- Binding expressions, which are observations of property changes. Property changes are reflected -in the view during the {@link api/angular.module.ng.$rootScope.Scope#$digest digest cycle}. -- Action expressions, which are expressions with side effects. Typically, the side effects cause -execution of a method in a controller in response to a user action, such as clicking on a button. - - -### Scope inheritance - -A scope (prototypically) inherits properties from its parent scope. Since a given property may not -reside on a child scope, if a property read does not find the property on a scope, the read will -recursively check the parent scope, grandparent scope, etc. all the way to the root scope before -defaulting to undefined. - -{@link guide/directive directives} associated with elements -(ngController, ngRepeat, ngInclude, etc.) create new child scopes that inherit properties from -the current parent scope. Any code in Angular is free to create a new scope. Whether or not your -code does so is an implementation detail of the directive, that is, you can decide when or if this -happens. Inheritance typically mimics HTML DOM element nesting, but does not do so with the same -granularity. - -A property write will always write to the current scope. This means that a write can hide a parent -property within the scope it writes to, as shown in the following example. - -<pre> -it('should inherit properties', inject(function($rootScope)) { - var root = $rootScope; - var child = root.$new(); - - root.name = 'angular'; - expect(child.name).toEqual('angular'); - expect(root.name).toEqual('angular'); - - child.name = 'super-heroic framework'; - expect(child.name).toEqual('super-heroic framework'); - expect(root.name).toEqual('angular'); -}); -</pre> - - -### Scope life cycle -1. **Creation** - - * The root scope is created by the {@link api/angular.module.ng.$rootScope $rootScope} service. - * To create a child scopes, you should call {@link api/angular.module.ng.$rootScope.Scope#$new parentScope.$new()}. - -2. **Watcher registration** - - Watcher registration can happen at any time and on any scope (root or child) via {@link -api/angular.module.ng.$rootScope.Scope#$watch scope.$watch()} API. - -3. **Model mutation** - - For mutations to be properly observed, you should make them only within the execution of the -function passed into {@link api/angular.module.ng.$rootScope.Scope#$apply scope.$apply()} call. (Angular apis do this -implicitly, so no extra `$apply` call is needed when doing synchronous work in controllers, or -asynchronous work with {@link api/angular.module.ng.$http $http} or {@link api/angular.module.ng.$defer -$defer} services. - -4. **Mutation observation** - - At the end of each `$apply` call {@link api/angular.module.ng.$rootScope.Scope#$digest $digest} cycle is started on -the root scope, which then propagates throughout all child scopes. - - During the `$digest` cycle, all `$watch-ers` expressions or functions are checked for model -mutation and if a mutation is detected, the `$watch-er` listener is called. - -5. **Scope destruction** - - When child scopes are no longer needed, it is the responsibility of the child scope creator to -destroy them via {@link api/angular.module.ng.$rootScope.Scope#$destroy 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. - - The root scope can't be destroyed via the `$destroy` API. Instead, it is enough to remove all -references from your application to the scope object and garbage collector will do its magic. -## Scopes in Angular applications -To understand how Angular applications work, you need to understand how scopes work within an -application. This section describes the typical life cycle of an application so you can see how -scopes come into play throughout and get a sense of their interactions. -### How scopes interact in applications - -1. At application compile time, a root scope is created and is attached to the root `<HTML>` DOM -element. -2. During the compilation phase, the {@link dev_guide.compiler compiler} matches {@link -guide/directive directives} against the DOM template. The directives -usually fall into one of two categories: - - Observing {@link guide/directive directives}, such as double-curly - expressions `{{expression}}`, register listeners using the {@link - api/angular.module.ng.$rootScope.Scope#$watch $watch()} method. This type of directive needs to - be notified whenever the expression changes so that it can update the view. - - Listener directives, such as {@link api/angular.module.ng.$compileProvider.directive.ngClick - ngClick}, register a listener with the DOM. When the DOM listener fires, the directive executes - the associated expression and updates the view using the {@link - api/angular.module.ng.$rootScope.Scope#$apply $apply()} method. -3. When an external event (such as a user action, timer or XHR) is received, the associated {@link -dev_guide.expressions expression} must be applied to the scope through the {@link -api/angular.module.ng.$rootScope.Scope#$apply $apply()} method so that all listeners are updated correctly. - - -### Directives that create scopes -In most cases, {@link guide/directive directives} and scopes interact but do not create new -instances of scope. However, some directives, such as {@link api/angular.module.ng.$compileProvider.directive.ngController -ngController} and {@link api/angular.module.ng.$compileProvider.directive.ngRepeat ngRepeat}, create new child scopes using -the {@link api/angular.module.ng.$rootScope.Scope#$new $new()} method and then attach the child scope to the -corresponding DOM element. You can retrieve a scope for any DOM element by using an -`angular.element(aDomElement).scope()` method call.) - - -### Controllers and scopes -Scopes and controllers interact with each other in the following situations: - - Controllers use scopes to expose controller methods to templates (see {@link -api/angular.module.ng.$compileProvider.directive.ngController ngController}). - - Controllers define methods (behavior) that can mutate the model (properties on the scope). - - Controllers may register {@link api/angular.module.ng.$rootScope.Scope#$watch watches} on the model. These watches -execute immediately after the controller behavior executes, but before the DOM gets updated. - -See the {@link dev_guide.mvc.understanding_controller controller docs} for more information. - -### Updating scope properties -You can update a scope by calling its {@link api/angular.module.ng.$rootScope.Scope#$apply $apply()} method with an -expression or a function as the function argument. However it is typically not necessary to do this -explicitly. In most cases, angular intercepts all external events (such as user interactions, XHRs, -and timers) and wraps their callbacks into the `$apply()` method call on the scope object for you -at the right time. The only time you might need to call `$apply()` explicitly is when you create -your own custom asynchronous widget or service. - -The reason it is unnecessary to call `$apply()` from within your controller functions when you use -built-in angular widgets and services is because your controllers are typically called from within -an `$apply()` call already. - -When a user inputs data, angularized widgets invoke `$apply()` on the current scope and evaluate an -angular expression or execute a function on this scope. Afterwards `$apply` will trigger `$digest` -call on the root scope, to propagate your changes through the entire system, which results in -$watch-ers firing and view getting updated. Similarly, when a request to fetch data from a server -is made and the response comes back, the data is written into the model (scope) within an $apply, -which then pushes updates through to the view and any other dependents. - -A widget that creates scopes (such as {@link api/angular.module.ng.$compileProvider.directive.ngRepeat ngRepeat}) via `$new`, -doesn't need to worry about propagating the `$digest` call from the parent scope to child scopes. -This happens automatically. - -## Scopes in unit-testing -You can create scopes, including the root scope, in tests by having the $rootScope injected into -your spec. This allows you to mimic the run-time environment and have full control over -the life cycle of the scope so that you can assert correct model transitions. Since these scopes -are created outside the normal compilation process, their life cycles must be managed by the test. - -### Using scopes in unit-testing -The following example demonstrates how the scope life cycle needs to be manually triggered from -within the unit-tests. - -<pre> - // example of a test - it('should trigger a watcher', inject(function($rootScope) { - var scope = $rootScope; - scope.$watch('name', function(name) { - scope.greeting = 'Hello ' + name + '!'; - }); - - scope.name = 'angular'; - // The watch does not fire yet since we have to manually trigger the digest phase. - expect(scope.greeting).toEqual(undefined); - - // manually trigger digest phase from the test - scope.$digest(); - expect(scope.greeting).toEqual('Hello Angular!'); - } -</pre> - - -### Dependency injection in Tests - -When you find it necessary to inject your own mocks in your tests, use a scope to override the -service instances, as shown in the following example. - -<pre> -it('should allow override of providers', inject( - function($provide) { - $provide.value('$location', {mode:'I am a mock'}); - }, - function($location){ - expect($location.mode).toBe('I am a mock'); - } -)}; -</pre> - -## Related Topics - -* {@link dev_guide.scopes Angular Scope Objects} -* {@link dev_guide.scopes.understanding_scopes Understanding Scopes} - -## Related API - -* {@link api/angular.module.ng.$rootScope.Scope Angular Scope API} - |
