| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | # View
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Overview
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | This document explains the concept of a View. | 
					
						
							|  |  |  | A View is a core primitive used by angular to render the DOM tree. | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  | A ViewContainer is location in a View which can accept child Views. | 
					
						
							|  |  |  | Every ViewContainer has an associated ViewContainerRef than can contain any number of child Views. | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  | Views form a tree structure which mimics the DOM tree. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | * View is a core rendering construct. A running application is just a collection of Views which are | 
					
						
							|  |  |  |   nested in a tree like structure. The View tree is a simplified version of the DOM tree. A View can | 
					
						
							|  |  |  |   have a single DOM Element or large DOM structures. The key is that the DOM tree in the View can | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |   not undergo structural changes (only property changes). | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | * Views represent a running instance of a DOM View. This implies that while elements in a View | 
					
						
							|  |  |  |   can change properties, they can not change structurally. (Structural changes such as, adding or | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |   removing elements requires adding or removing child Views into ViewContainers). | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  | * View can have zero or more ViewContainers. A ViewContainer is a marker in the DOM which allows | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |   the insertion of child Views. | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | * Views are created from a ProtoView. A ProtoView is a compiled DOM View which is efficient at | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |   creating Views. | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | * View contains a context object. The context represents the object instance against which all | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |   expressions are evaluated. | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | * View contains a ChangeDetector for looking for detecting changes to the model. | 
					
						
							|  |  |  | * View contains ElementInjector for creating Directives. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Simple View
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Let's examine a simple View and all of its parts in detail. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Assume the following Component: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | class Greeter { | 
					
						
							|  |  |  |   greeting:string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   constructor() { | 
					
						
							|  |  |  |     this.greeting = 'Hello'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-09 21:20:11 +02:00
										 |  |  | And assume following HTML View: | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | <div> | 
					
						
							|  |  |  |   Your name: | 
					
						
							|  |  |  |   <input var="name" type="Text"> | 
					
						
							|  |  |  |   <br> | 
					
						
							|  |  |  |   {{greeting}} {{name.value}}! | 
					
						
							|  |  |  | </div> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | The above template is compiled by the Compiler to create a ProtoView. The ProtoView is then used to | 
					
						
							|  |  |  | create an instance of the View. The instantiation process involves cloning the above template and | 
					
						
							|  |  |  | locating all of the elements which contain bindings and finally instantiating the Directives | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  | associated with the template. (See compilation for more details.) | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | <div>                             | viewA(greeter) | 
					
						
							|  |  |  |   Your name:                      | viewA(greeter) | 
					
						
							|  |  |  |   <input var="name" type="Text">  | viewA(greeter): local variable 'name' | 
					
						
							|  |  |  |   <br>                            | viewA(greeter) | 
					
						
							|  |  |  |   {{greeting}} {{name.value}}!    | viewA(greeter): binding expression 'greeting' & 'name.value' | 
					
						
							|  |  |  | </div>                            | viewA(greeter) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The resulting View instance looks something like this (simplified pseudo code): | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | viewA = new View({ | 
					
						
							|  |  |  |   template: ..., | 
					
						
							|  |  |  |   context: new Greeter(), | 
					
						
							|  |  |  |   localVars: ['name'], | 
					
						
							|  |  |  |   watchExp: ['greeting', 'name.value'] | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Note: | 
					
						
							|  |  |  | * View uses instance of `Greeter` as the evaluation context. | 
					
						
							|  |  |  | * View knows of local variables `name`. | 
					
						
							|  |  |  | * View knows which expressions need to be watched. | 
					
						
							|  |  |  | * View knows what needs to be updated if the watched expression changes. | 
					
						
							|  |  |  | * All DOM elements are owned by single instance of the view. | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | * The structure of the DOM can not change during runtime. To allow structural changes to the DOM we need | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |   to understand Composed View. | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Composed View
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | An important part of an application is to be able to change the DOM structure to render data for the | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  | user. In Angular this is done by inserting child views into the ViewContainer. | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-09 21:20:11 +02:00
										 |  |  | Let's start with a View such as: | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | <ul> | 
					
						
							| 
									
										
										
										
											2015-02-04 22:27:31 +01:00
										 |  |  |   <li template="foreach: person in people">{{person}}</li> | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | </ul> | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | During the compilation process the Compiler breaks the HTML template into these two ProtoViews: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  |   <li>{{person}}</li>   | protoViewB(Locals) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | and | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2015-02-14 20:06:20 +01:00
										 |  |  | <ul>                    | protoViewA(someContext) | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  |   <template></template> | protoViewA(someContext): protoViewB | 
					
						
							| 
									
										
										
										
											2015-02-14 20:06:20 +01:00
										 |  |  | </ul>                   | protoViewA(someContext) | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-14 20:06:20 +01:00
										 |  |  | The next step is to compose these two ProtoViews into an actual view which is rendered to the user. | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | *Step 1:* Instantiate `viewA` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2015-02-14 20:06:20 +01:00
										 |  |  | <ul>                    | viewA(someContext) | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  |   <template></template> | viewA(someContext): new Foreach(new ViewContainer(protoViewB)) | 
					
						
							| 
									
										
										
										
											2015-02-14 20:06:20 +01:00
										 |  |  | </ul>                   | viewA(someContext) | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | *Step2:* Instantiate `Foreach` directive which will receive the `ViewContainerRef`. (The ViewContainerRef | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  | has a reference to `protoViewA`). | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | *Step3:* As the `Foreach` directive unrolls it asks the `ViewContainerRef` to instantiate `protoViewB` and insert | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  | it after the `ViewContainer` anchor. This is repeated for each `person` in `people`. Notice that | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | <ul>                    | viewA(someContext) | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  |   <template></template> | viewA(someContext): new Foreach(new ViewContainer(protoViewB)) | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  |   <li>{{person}}</li>   | viewB0(locals0(someContext)) | 
					
						
							|  |  |  |   <li>{{person}}</li>   | viewB1(locals0(someContext)) | 
					
						
							| 
									
										
										
										
											2015-02-14 20:06:20 +01:00
										 |  |  | </ul>                   | viewA(someContext) | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | *Step4:* All of the bindings in the child Views are updated. Notice that in the case of `Foreach` | 
					
						
							|  |  |  | the evaluation context for the `viewB0` and `viewB1` are `locals0` and `locals1` respectively. | 
					
						
							|  |  |  | Locals allow the introduction of new local variables visible only within the scope of the View, and | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  | delegate any unknown references to the parent context. | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | <ul>                    | viewA | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  |   <template></template> | viewA: new Foreach(new ViewContainer(protoViewB)) | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  |   <li>Alice</li>        | viewB0 | 
					
						
							|  |  |  |   <li>Bob</li>          | viewB1 | 
					
						
							|  |  |  | </ul>                   | viewA | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  | Each View can have zero or more ViewContainers. By inserting and removing child Views to and from the | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | ViewContainers, the application can mutate the DOM structure to any desirable state. A View may contain | 
					
						
							|  |  |  | individual nodes or a complex DOM structure. The insertion points for the child Views, known as | 
					
						
							|  |  |  | ViewContainers, contain a DOM element which acts as an anchor. The anchor is either a `template` or | 
					
						
							|  |  |  | a `script` element depending on your browser. It is used to identify where the child Views will be | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  | inserted. | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | ## Component Views
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | A View can also contain Components. Components contain Shadow DOM for encapsulating their internal | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  | rendering state. Unlike ViewContainers which can contain zero or more Views, the Component always contains | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  | exactly one Shadow View. | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | <div>                            | viewA | 
					
						
							|  |  |  |   <my-component>                 | viewA | 
					
						
							|  |  |  |     #SHADOW_ROOT                 | (encapsulation boundary) | 
					
						
							|  |  |  |       <div>                      |   viewB | 
					
						
							|  |  |  |          encapsulated rendering  |   viewB | 
					
						
							|  |  |  |       </div>                     |   viewB | 
					
						
							|  |  |  |   </my-component>                | viewA | 
					
						
							|  |  |  | </div>                           | viewA | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Evaluation Context
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-14 20:06:20 +01:00
										 |  |  | Each View acts as a context for evaluating its expressions. There are two kinds of contexts: | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 1. A component controller instance and | 
					
						
							| 
									
										
										
										
											2015-02-14 20:06:20 +01:00
										 |  |  | 2. a `Locals` context for introducing local variables into the View. | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Let's assume following component: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | class Greeter { | 
					
						
							|  |  |  |   greeting:string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   constructor() { | 
					
						
							|  |  |  |     this.greeting = 'Hello'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-09 21:20:11 +02:00
										 |  |  | And assume the following HTML View: | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | <div>                             | viewA(greeter) | 
					
						
							|  |  |  |   Your name:                      | viewA(greeter) | 
					
						
							|  |  |  |   <input var="name" type="Text">  | viewA(greeter) | 
					
						
							|  |  |  |   <br>                            | viewA(greeter) | 
					
						
							|  |  |  |   {{greeting}} {{name.value}}!    | viewA(greeter) | 
					
						
							|  |  |  | </div>                            | viewA(greeter) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | The above UI is built using a single View, and hence a single context `greeter`. It can be expressed | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  | in this pseudo-code. | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | var greeter = new Greeter(); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The View contains two bindings: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1. `greeting`: This is bound to the `greeting` property on the `Greeter` instance. | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | 2. `name.value`: This poses a problem. There is no `name` property on the `Greeter` instance. To solve | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  | this we wrap the `Greeter` instance in the `Local` instance like so: | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | ``` | 
					
						
							|  |  |  | var greeter = new Locals(new Greeter(), {name: ref_to_input_element }) | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | By wrapping the `Greeter` instance into the `Locals` we allow the view to introduce variables which | 
					
						
							|  |  |  | are in addition to the `Greeter` instance. During the resolution of the expressions we first check | 
					
						
							| 
									
										
										
										
											2015-02-14 20:06:20 +01:00
										 |  |  | the locals, and then the `Greeter` instance. | 
					
						
							| 
									
										
										
										
											2014-12-08 14:29:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## View LifeCycle (Hydration and Dehydration)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Views transition through a particular set of states: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1. View is created from the ProtoView. | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | 2. View can be attached to an existing ViewContainerRef. | 
					
						
							|  |  |  | 3. Upon attaching View to the ViewContainerRef the View needs to be hydrated. The hydration process | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |    involves instantiating all of the Directives associated with the current View. | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | 4. At this point the view is ready and renderable. Multiple changes can be delivered to the | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |    Directives from the ChangeDetection. | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | 5. At some point the View can be removed. At this point all of the directives are destroyed during | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |    the dehydration process and the view becomes inactive. | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | 6. The View has to wait until it is detached from the DOM. The delay in detaching could be caused | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |    because an animation is animating the view away. | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | 7. After the View is detached from the DOM it is ready to be reused. The view reuse allows the | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |    application to be faster in subsequent renderings. |