From dd38ce6585b0e7ffa755f4c65d78ed90204729d1 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Tue, 28 Feb 2012 12:14:47 -0800 Subject: docs(scope): rewrite --- .../dev_guide.mvc.understanding_controller.ngdoc | 2 +- .../guide/dev_guide.mvc.understanding_model.ngdoc | 2 +- .../content/guide/dev_guide.scopes.internals.ngdoc | 230 -------------- docs/content/guide/dev_guide.scopes.ngdoc | 35 --- .../dev_guide.scopes.understanding_scopes.ngdoc | 66 ----- .../guide/dev_guide.templates.databinding.ngdoc | 2 +- docs/content/guide/index.ngdoc | 13 +- docs/content/guide/scope.ngdoc | 330 +++++++++++++++++++++ docs/content/misc/started.ngdoc | 2 +- 9 files changed, 338 insertions(+), 344 deletions(-) delete mode 100644 docs/content/guide/dev_guide.scopes.internals.ngdoc delete mode 100644 docs/content/guide/dev_guide.scopes.ngdoc delete mode 100644 docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc create mode 100644 docs/content/guide/scope.ngdoc (limited to 'docs') diff --git a/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc b/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc index edaddf66..cfe223c6 100644 --- a/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc +++ b/docs/content/guide/dev_guide.mvc.understanding_controller.ngdoc @@ -3,7 +3,7 @@ @description In angular, a controller is a JavaScript function(type/class) that is used to augment instances of -angular {@link dev_guide.scopes Scope}, excluding the root scope. When you or angular create a new +angular {@link scope Scope}, excluding the root scope. When you or angular create a new child scope object via the {@link api/angular.module.ng.$rootScope.Scope#$new scope.$new} API , there is an option to pass in a controller as a method argument. This will tell angular to associate the controller with the new scope and to augment its behavior. diff --git a/docs/content/guide/dev_guide.mvc.understanding_model.ngdoc b/docs/content/guide/dev_guide.mvc.understanding_model.ngdoc index 06557b8d..b8c08198 100644 --- a/docs/content/guide/dev_guide.mvc.understanding_model.ngdoc +++ b/docs/content/guide/dev_guide.mvc.understanding_model.ngdoc @@ -7,7 +7,7 @@ either a single object representing one entity (for example, a model called "pho being an array of phones) or the entire data model for the application (all entities). In angular, a model is any data that is reachable as a property of an angular {@link -dev_guide.scopes Scope} object. The name of the property is the model identifier and the value is +scope Scope} object. The name of the property is the model identifier and the value is any JavaScript object (including arrays and primitives). The only requirement for a JavaScript object to be a model in angular is that the object must be 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. - -
-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');
-});
-
- - -### 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 `` 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. - -
-  // 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!');
-  }
-
- - -### 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. - -
-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');
-  }
-)};
-
- -## 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} - diff --git a/docs/content/guide/dev_guide.scopes.ngdoc b/docs/content/guide/dev_guide.scopes.ngdoc deleted file mode 100644 index 6ddbcae4..00000000 --- a/docs/content/guide/dev_guide.scopes.ngdoc +++ /dev/null @@ -1,35 +0,0 @@ -@ngdoc overview -@name Developer Guide: Scopes -@description - - -An Angular scope is a JavaScript object with additional APIs useful for watching property changes, -Angular scope is the model in Model-View-Controller paradigm. Instances of scope serve as the -context within which all {@link dev_guide.expressions expressions} get evaluated. - -You can think of Angular scope objects as the medium through which the model, view, and controller -communicate. Scopes are linked during the compilation process with the view. This linkage provides -the contexts in which Angular creates data-bindings between the model and the view. - -In addition to providing the context in which data is evaluated, Angular scope objects watch for -model changes. The scope objects also notify all components interested in any model changes (for -example, functions registered through {@link api/angular.module.ng.$rootScope.Scope#$watch $watch}, bindings created by -{@link api/angular.module.ng.$compileProvider.directive.ngBind ngBind}, or HTML input elements). - -Angular scope objects: - -* Link the model, controller and view template together. -* Provide the mechanism to watch for model changes ({@link api/angular.module.ng.$rootScope.Scope#$watch $watch}). -* Apply model changes to the system ({@link api/angular.module.ng.$rootScope.Scope#$apply $apply}). -* Provide the context in which expressions are evaluated ({@link api/angular.module.ng.$rootScope.Scope#$eval $eval}). - - -## Related Topics - -* {@link dev_guide.scopes.understanding_scopes Understanding Scopes} -* {@link dev_guide.scopes.internals Scopes Internals} - -## Related API - -* {@link api/angular.module.ng.$rootScope.Scope Angular Scope API} - diff --git a/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc b/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc deleted file mode 100644 index aeab3191..00000000 --- a/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc +++ /dev/null @@ -1,66 +0,0 @@ -@ngdoc overview -@name Developer Guide: Scopes: Understanding Scopes -@description - -Angular automatically creates a root scope during initialization, and attaches it to the page's -root DOM element (usually ``). The root scope object, along with any of its child scope -objects, serves as the infrastructure on which your data model is built. The data model (JavaScript -objects, arrays, or primitives) is attached to angular scope properties. Angular binds the property -values to the DOM where bindings are specified in the template. Angular attaches any controller -functions you have created to their respective scope objects. - - - -Angular scopes can be nested, so a child scope has a parent scope upstream in the DOM. When you -display an angular expression in the view, angular walks the DOM tree looking in the closest -attached scope object for the specified data. If it doesn't find the data in the closest attached -scope, it looks further up the scope hierarchy until it finds the data. - -A child scope object inherits properties from its parents. For example, in the following snippet of -code, observe how the value of `name` changes, based on the HTML element it is displayed in: - - - - -
Name={{name}}
-
- - it('should override the name property', function() { - expect(using('.doc-example-live').repeater('li').row(0)). - toEqual(['Igor']); - expect(using('.doc-example-live').repeater('li').row(1)). - toEqual(['Misko']); - - expect(using('.doc-example-live').repeater('li').row(2)). - toEqual(['Gail']); - expect(using('.doc-example-live').repeater('li').row(3)). - toEqual(['Kai']); - expect(using('.doc-example-live').element('pre').text()). - toBe('Name=Hank'); - }); - -
- -The angular {@link api/angular.module.ng.$compileProvider.directive.ngRepeat ngRepeat} directive creates a new scope for each -element that it repeats (in this example the elements are list items). In the `