diff options
Diffstat (limited to 'docs/content')
| -rw-r--r-- | docs/content/cookbook/mvc.ngdoc | 2 | ||||
| -rw-r--r-- | docs/content/guide/dev_guide.scopes.controlling_scopes.ngdoc | 39 | ||||
| -rw-r--r-- | docs/content/guide/dev_guide.scopes.internals.ngdoc | 196 | ||||
| -rw-r--r-- | docs/content/guide/dev_guide.scopes.ngdoc | 30 | ||||
| -rw-r--r-- | docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc | 4 | ||||
| -rw-r--r-- | docs/content/guide/dev_guide.scopes.updating_scopes.ngdoc | 38 | ||||
| -rw-r--r-- | docs/content/guide/dev_guide.scopes.working_scopes.ngdoc | 52 | ||||
| -rw-r--r-- | docs/content/guide/index.ngdoc | 4 |
8 files changed, 213 insertions, 152 deletions
diff --git a/docs/content/cookbook/mvc.ngdoc b/docs/content/cookbook/mvc.ngdoc index 6a167469..d757baff 100644 --- a/docs/content/cookbook/mvc.ngdoc +++ b/docs/content/cookbook/mvc.ngdoc @@ -64,7 +64,7 @@ no connection between the controller and the view. }); this.$location.hashSearch.board = rows.join(';') + '/' + this.nextMove; }, - readUrl: function(value) { + readUrl: function(scope, value) { if (value) { value = value.split('/'); this.nextMove = value[1]; diff --git a/docs/content/guide/dev_guide.scopes.controlling_scopes.ngdoc b/docs/content/guide/dev_guide.scopes.controlling_scopes.ngdoc deleted file mode 100644 index cdbad444..00000000 --- a/docs/content/guide/dev_guide.scopes.controlling_scopes.ngdoc +++ /dev/null @@ -1,39 +0,0 @@ -@workInProgress -@ngdoc overview -@name Developer Guide: Scopes: Applying Controllers to Scopes -@description - -When a controller function is applied to a scope, the scope is augmented with the behavior defined -in the controller. The end result is that the scope behaves as if it were the controller: - -<pre> -var scope = angular.scope(); -scope.salutation = 'Hello'; -scope.name = 'World'; - -expect(scope.greeting).toEqual(undefined); - -scope.$watch('name', function(){ -this.greeting = this.salutation + ' ' + this.name + '!'; -}); - -expect(scope.greeting).toEqual('Hello World!'); -scope.name = 'Misko'; -// scope.$eval() will propagate the change to listeners -expect(scope.greeting).toEqual('Hello World!'); - -scope.$eval(); -expect(scope.greeting).toEqual('Hello Misko!'); -</pre> - - -## Related Topics - -* {@link dev_guide.scopes Angular Scope Objects} -* {@link dev_guide.scopes.understanding_scopes Understanding Angular Scopes} -* {@link dev_guide.scopes.working_scopes Working With Angular Scopes} -* {@link dev_guide.scopes.updating_scopes Updating Angular Scopes} - -## Related API - -* {@link api/angular.scope Angular Scope API} diff --git a/docs/content/guide/dev_guide.scopes.internals.ngdoc b/docs/content/guide/dev_guide.scopes.internals.ngdoc new file mode 100644 index 00000000..3aed7970 --- /dev/null +++ b/docs/content/guide/dev_guide.scopes.internals.ngdoc @@ -0,0 +1,196 @@ +@workInProgress +@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 ($watch and $observe) to observe model mutations. +- Scopes provide APIs ($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 functionality will change before 1.0 is +released.) + + +### Root scope + +Every application has a root scope, which is the ancestor of all other scopes. The root scope is +responsible for creating the injector which is assigned to the {@link api/angular.scope.$service +$service} property, and initializing the services. + +### What is scope used for? + +{@link dev_guide.expressions Expressions} in the view are 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.scope.$flush flush 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 api/angular.directive Directives} associated with elements (ng:controller, ng:repeat, +ng:include, 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> +var root = angular.scope(); +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> + + + +## 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. + 1. The root scope creates an {@link api/angular.injector injector} which is assigned to the +{@link api/angular.scope.$service $service} property of the root scope. + 2. Any eager {@link api/angular.scope.$service services} are initialized at this point. +2. During the compilation phase, the {@link dev_guide.compiler compiler} matches {@link +api/angular.directive directives} against the DOM template. The directives usually fall into one of +two categories: + - Observing {@link api/angular.directive directives}, such as double-curly expressions +`{{expression}}`, register listeners using the {@link api/angular.scope.$observe $observe()} +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.directive.ng:click ng:click}, 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.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.scope.$apply $apply()} method so that all listeners are updated correctly. + + +### Directives that create scopes +In most cases, {@link api/angular.directive directives} and scopes interact but do not create new +instances of scope. However, some directives, such as {@link api/angular.directive.ng:controller +ng:controller} and {@link api/angular.widget.@ng:repeat ng:repeat}, create new child scopes using +the {@link api/angular.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.directive.ng:controller ng:controller}). + - Controllers define methods (behavior) that can mutate the model (properties on the scope). + - Controllers may register {@link api/angular.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.scope.$eval $eval()} method, but usually +you do not have to do this explicitly. In most cases, angular intercepts all external events (such +as user interactions, XHRs, and timers) and calls the `$eval()` method on the scope object for you +at the right time. The only time you might need to call `$eval()` explicitly is when you create +your own custom widget or service. + +The reason it is unnecessary to call `$eval()` from within your controller functions when you use +built-in angular widgets and services is because a change in the data model triggers a call to the +`$eval()` method on the scope object where the data model changed. + +When a user inputs data, angularized widgets copy the data to the appropriate scope and then call +the `$eval()` method on the root scope to update the view. It works this way because scopes are +inherited, and a child scope `$eval()` overrides its parent's `$eval()` method. Updating the whole +page requires a call to `$eval()` on the root scope as `$root.$eval()`. Similarly, when a request +to fetch data from a server is made and the response comes back, the data is written into the model +and then `$eval()` is called to push updates through to the view and any other dependents. + +A widget that creates scopes (such as {@link api/angular.widget.@ng:repeat ng:repeat}) is +responsible for forwarding `$eval()` calls from the parent to those child scopes. That way, calling +`$eval()` on the root scope will update the whole page. This creates a spreadsheet-like behavior +for your app; the bound views update immediately as the user enters data. + +## Scopes in unit-testing +You can create scopes, including the root scope, in tests using the {@link api/angular.scope} API. +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. + +There is a key difference between the way scopes are called in Angular applications and in Angular +tests. In tests, the {@link api/angular.service.$updateView $updateView} calls the {@link +api/angular.scope.$flush $flush()} method synchronously.(This is in contrast to the asynchronous +calls used for applications.) Because test calls to scopes are synchronous, your tests are simpler +to write. + +### 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 + var scope = angular.scope(); + scope.$watch('name', function(scope, 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> +var myLocation = {}; +var scope = angular.scope(null, {$location: myLocation}); +expect(scope.$service('$location')).toEqual(myLocation); +</pre> + +## Related Topics + +* {@link dev_guide.scopes Angular Scope Objects} +* {@link dev_guide.scopes.understanding_scopes Understanding Scopes} + +## Related API + +* {@link api/angular.scope Angular Scope API} + diff --git a/docs/content/guide/dev_guide.scopes.ngdoc b/docs/content/guide/dev_guide.scopes.ngdoc index e9706e2f..6ebd5501 100644 --- a/docs/content/guide/dev_guide.scopes.ngdoc +++ b/docs/content/guide/dev_guide.scopes.ngdoc @@ -1,36 +1,34 @@ @workInProgress @ngdoc overview -@name Developer Guide: Angular Scopes +@name Developer Guide: Scopes @description -An angular scope is a JavaScript type defined by angular. Instances of this type are objects that -serve as the context within which all model and controller methods live and get evaluated. +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. -Angular links scope objects to specific points in a compiled (processed) template. This linkage -provides the contexts in which angular creates data-bindings between the model and the view. You -can think of angular scope objects as the medium through which the model, view, and controller -communicate. +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 +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.scope.$watch $watch}, bindings created by {@link api/angular.directive.ng:bind ng:bind}, or HTML input elements). -Angular scope objects are responsible for: +Angular scope objects: -* Gluing the model, controller and view template together. -* Providing the mechanism to watch for model changes ({@link api/angular.scope.$watch}). -* Notifying interested components when the model changes ({@link api/angular.scope.$eval}). -* Providing the context in which all controller functions and angular expressions are evaluated. +* Link the model, controller and view template together. +* Provide the mechanism to watch for model changes ({@link api/angular.scope.$watch}). +* Notify interested components when the model changes ({@link api/angular.scope.$eval}). +* Provide the context in which expressions are evaluated. ## Related Topics * {@link dev_guide.scopes.understanding_scopes Understanding Scopes} -* {@link dev_guide.scopes.working_scopes Working With Scopes} -* {@link dev_guide.scopes.controlling_scopes Applying Controllers to Scopes} -* {@link dev_guide.scopes.updating_scopes Updating Scopes} +* {@link dev_guide.scopes.internals Scopes Internals} ## Related API diff --git a/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc b/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc index 704c9241..57804462 100644 --- a/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc +++ b/docs/content/guide/dev_guide.scopes.understanding_scopes.ngdoc @@ -60,9 +60,7 @@ The following illustration shows the DOM and angular scopes for the example abov ## Related Topics * {@link dev_guide.scopes Angular Scope Objects} -* {@link dev_guide.scopes.working_scopes Working With Scopes} -* {@link dev_guide.scopes.controlling_scopes Applying Controllers to Scopes} -* {@link dev_guide.scopes.updating_scopes Updating Scopes} +* {@link dev_guide.scopes.internals Scopes Internals} ## Related API diff --git a/docs/content/guide/dev_guide.scopes.updating_scopes.ngdoc b/docs/content/guide/dev_guide.scopes.updating_scopes.ngdoc deleted file mode 100644 index 2d5f1725..00000000 --- a/docs/content/guide/dev_guide.scopes.updating_scopes.ngdoc +++ /dev/null @@ -1,38 +0,0 @@ -@workInProgress -@ngdoc overview -@name Developer Guide: Scopes: Updating Scope Properties -@description - -You can update a scope by calling its {@link api/angular.scope.$eval $eval()} method, but usually -you do not have to do this explicitly. In most cases, angular intercepts all external events (such -as user interactions, XHRs, and timers) and calls the `$eval()` method on the scope object for you -at the right time. The only time you might need to call `$eval()` explicitly is when you create -your own custom widget or service. - -The reason it is unnecessary to call `$eval()` from within your controller functions when you use -built-in angular widgets and services is because a change in the data model triggers a call to the -`$eval()` method on the scope object where the data model changed. - -When a user inputs data, angularized widgets copy the data to the appropriate scope and then call -the `$eval()` method on the root scope to update the view. It works this way because scopes are -inherited, and a child scope `$eval()` overrides its parent's `$eval()` method. Updating the whole -page requires a call to `$eval()` on the root scope as `$root.$eval()`. Similarly, when a request -to fetch data from a server is made and the response comes back, the data is written into the model -and then `$eval()` is called to push updates through to the view and any other dependents. - -A widget that creates scopes (such as {@link api/angular.widget.@ng:repeat ng:repeat}) is -responsible for forwarding `$eval()` calls from the parent to those child scopes. That way, calling -`$eval()` on the root scope will update the whole page. This creates a spreadsheet-like behavior -for your app; the bound views update immediately as the user enters data. - - -## Related Documents - -* {@link dev_guide.scopes Angular Scope Objects} -* {@link dev_guide.scopes.understanding_scopes Understanding Angular Scope Objects} -* {@link dev_guide.scopes.working_scopes Working With Angular Scopes} -* {@link dev_guide.scopes.controlling_scopes Applying Controllers to Scopes} - -## Related API - -* {@link api/angular.scope Angular Scope API} diff --git a/docs/content/guide/dev_guide.scopes.working_scopes.ngdoc b/docs/content/guide/dev_guide.scopes.working_scopes.ngdoc deleted file mode 100644 index 8e4503a5..00000000 --- a/docs/content/guide/dev_guide.scopes.working_scopes.ngdoc +++ /dev/null @@ -1,52 +0,0 @@ -@workInProgress -@ngdoc overview -@name Developer Guide: Scopes: Working With Angular Scopes -@description - -When you use {@link api/angular.directive.ng:autobind ng:autobind} to bootstrap your application, -angular creates the root scope automatically for you. If you need more control over the -bootstrapping process, or if you need to create a root scope for a test, you can do so using the -{@link api/angular.scope angular.scope()} API. - -Here is a simple code snippet that demonstrates how to create a scope object, assign model -properties to it, and register listeners to watch for changes to the model properties: - -<pre> -var scope = angular.scope(); -scope.salutation = 'Hello'; -scope.name = 'World'; - -// Verify that greeting is undefined -expect(scope.greeting).toEqual(undefined); - -// Set up the watcher... -scope.$watch('name', function(){ -// when 'name' changes, set 'greeting'... -this.greeting = this.salutation + ' ' + this.name + '!'; -} -); - -// verify that 'greeting' was set... -expect(scope.greeting).toEqual('Hello World!'); - -// 'name' changed! -scope.name = 'Misko'; - -// scope.$eval() will propagate the change to listeners -expect(scope.greeting).toEqual('Hello World!'); - -scope.$eval(); -// verify that '$eval' propagated the change -expect(scope.greeting).toEqual('Hello Misko!'); -</pre> - -## Related Topics - -* {@link dev_guide.scopes Angular Scope Objects} -* {@link dev_guide.scopes.understanding_scopes Understanding Scopes} -* {@link dev_guide.scopes.controlling_scopes Applying Controllers to Scopes} -* {@link dev_guide.scopes.updating_scopes Updating Scopes} - -## Related API - -* {@link api/angular.scope Angular Scope API} diff --git a/docs/content/guide/index.ngdoc b/docs/content/guide/index.ngdoc index c40bb1be..b2aab161 100644 --- a/docs/content/guide/index.ngdoc +++ b/docs/content/guide/index.ngdoc @@ -30,9 +30,7 @@ of the following documents before returning here to the Developer Guide: ## {@link dev_guide.scopes Angular Scope Objects} * {@link dev_guide.scopes.understanding_scopes Understanding Angular Scope Objects} -* {@link dev_guide.scopes.working_scopes Working With Angular Scopes} -* {@link dev_guide.scopes.controlling_scopes Applying Controllers to Scopes} -* {@link dev_guide.scopes.updating_scopes Updating Scope Properties} +* {@link dev_guide.scopes.internals Angular Scope Internals} ## {@link dev_guide.compiler Angular HTML Compiler} |
