docs: annotations
This commit is contained in:
parent
2ff2ce3c6c
commit
f822066e2a
|
@ -14,7 +14,8 @@ import {Injectable} from 'angular2/di';
|
||||||
* elements in the DOM, the following steps occur:
|
* elements in the DOM, the following steps occur:
|
||||||
*
|
*
|
||||||
* 1. For each directive, the [ElementInjector] attempts to resolve the directive's constructor arguments.
|
* 1. For each directive, the [ElementInjector] attempts to resolve the directive's constructor arguments.
|
||||||
* 2. Angular instantiates directives for each matched element using [ElementInjector].
|
* 2. Angular instantiates directives for each matched element using [ElementInjector] in a depth-first order,
|
||||||
|
* as declared in the HTML.
|
||||||
*
|
*
|
||||||
* ## Understanding How Injection Works
|
* ## Understanding How Injection Works
|
||||||
*
|
*
|
||||||
|
@ -28,37 +29,40 @@ import {Injectable} from 'angular2/di';
|
||||||
* - *Element Injectors*: Each component has a Shadow DOM. Within the Shadow DOM each element has an [ElementInjector]
|
* - *Element Injectors*: Each component has a Shadow DOM. Within the Shadow DOM each element has an [ElementInjector]
|
||||||
* which follow the same parent-child hiercachy as the DOM elements themselves.
|
* which follow the same parent-child hiercachy as the DOM elements themselves.
|
||||||
*
|
*
|
||||||
* When resolving dependencies, the current injector is asked to resolve the dependency first, and if it does not
|
* When a template is instantiated, it also must instantiate the corresponding directives in a depth-first order. The
|
||||||
* have it, it delegates to the parent injector.
|
* current [ElementInjector] resolves the constructor dependencies for each directive.
|
||||||
*
|
*
|
||||||
* Angular then resolves dependencies as follows, according to the order in which they appear in the [View]:
|
* Angular then resolves dependencies as follows, according to the order in which they appear in the [View]:
|
||||||
*
|
*
|
||||||
* 1. Dependencies on element injectors and their parents until it encounters a Shadow DOM boundary
|
* 1. Dependencies on the current element
|
||||||
* 2. Dependencies on component injectors and their parents until it encounters the root component
|
* 2. Dependencies on element injectors and their parents until it encounters a Shadow DOM boundary
|
||||||
* 3. Dependencies on pre-existing injectors
|
* 3. Dependencies on component injectors and their parents until it encounters the root component
|
||||||
|
* 4. Dependencies on pre-existing injectors
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* The [ElementInjector] can inject other directives, element-specific special objects, or can delegate to the parent
|
* The [ElementInjector] can inject other directives, element-specific special objects, or it can delegate to the parent
|
||||||
* injector.
|
* injector.
|
||||||
*
|
*
|
||||||
* To inject other directives, declare the constructor parameter as:
|
* To inject other directives, declare the constructor parameter as:
|
||||||
* - `directive:DirectiveType`: a directive on the current element only
|
* - `directive:DirectiveType`: a directive on the current element only
|
||||||
* - `@Ancestor() d:Type`: any directive that matches the type between the current element (excluded) and the Shadow DOM root [TODO: what does (excluded) mean? Does this apply to the @Parent annotation also?]
|
* - `@Ancestor() directive:DirectiveType`: any directive that matches the type between the current element and the
|
||||||
* - `@Parent() d:Type`: any directive that matches the type on a direct parent element only
|
* Shadow DOM root. Current Element is not included in the resolution, therefor even if it could resolve it, it will
|
||||||
* - `@Children query:Query<Type>`: A live collection of direct child directives
|
* be ignored.
|
||||||
* - `@Descendants query:Query<Type>`: A live collection of any child directives
|
* - `@Parent() directive:DirectiveType`: any directive that matches the type on a direct parent element only.
|
||||||
|
* - `@Children query:Query<DirectiveType>`: A live collection of direct child directives [TO BE IMPLEMENTED].
|
||||||
|
* - `@Descendants query:Query<DirectiveType>`: A live collection of any child directives [TO BE IMPLEMENTED].
|
||||||
*
|
*
|
||||||
* To inject element-specific special objects, declare the constructor parameter as:
|
* To inject element-specific special objects, declare the constructor parameter as:
|
||||||
* - `element: NgElement` to obtain a DOM element (DEPRECATED: replacment coming)
|
* - `element: NgElement` to obtain a DOM element (DEPRECATED: replacment coming)
|
||||||
* - `viewContainer: ViewContainer` to control child template instantiation, for [Viewport] directives only
|
* - `viewContainer: ViewContainer` to control child template instantiation, for [Viewport] directives only
|
||||||
* - `bindingPropagation: BindingPropagation` to control change detection in a more granular way
|
* - `bindingPropagation: BindingPropagation` to control change detection in a more granular way.
|
||||||
*
|
*
|
||||||
* ## Example
|
* ## Example
|
||||||
*
|
*
|
||||||
* The following example demonstrates how dependency injection resolves constructor arguments in practice.
|
* The following example demonstrates how dependency injection resolves constructor arguments in practice.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Assume this HTML structure:
|
* Assume this HTML template:
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* <div dependency="1">
|
* <div dependency="1">
|
||||||
|
@ -93,9 +97,10 @@ import {Injectable} from 'angular2/di';
|
||||||
*
|
*
|
||||||
* Let's step through the different ways in which `MyDirective` could be declared...
|
* Let's step through the different ways in which `MyDirective` could be declared...
|
||||||
*
|
*
|
||||||
|
*
|
||||||
* ### No injection
|
* ### No injection
|
||||||
*
|
*
|
||||||
* Here the constructor is declared with no arguments, so nothing is injected into `MyDirective`.
|
* Here the constructor is declared with no arguments, therefore nothing is injected into `MyDirective`.
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* @Decorator({ selector: '[my-directive]' })
|
* @Decorator({ selector: '[my-directive]' })
|
||||||
|
@ -105,9 +110,8 @@ import {Injectable} from 'angular2/di';
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* This directive would return nothing for the example code above. [TODO: True? We spent a lot of time talking about
|
* This directive would be instantiated with no dependencies.
|
||||||
* errors but in this case, there's nothing to error on, right? I don't understand the diff between "returns" and "injects"
|
*
|
||||||
* when the example is showing a directive not the template. Which is the correct verb?]
|
|
||||||
*
|
*
|
||||||
* ### Component-level injection
|
* ### Component-level injection
|
||||||
*
|
*
|
||||||
|
@ -124,7 +128,8 @@ import {Injectable} from 'angular2/di';
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* This directive would return `dependency=3` for the example code above. [TODO: True? Is "return" the right verb?]
|
* This directive would be instantiated with a dependency on `SomeService`.
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* ### Injecting a directive from the current element
|
* ### Injecting a directive from the current element
|
||||||
*
|
*
|
||||||
|
@ -138,14 +143,14 @@ import {Injectable} from 'angular2/di';
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
* This directive would also return `dependency=3` for the example code above. [TODO: True? Why is this the same?]
|
* This directive would be instantiated with `Dependency` declared at the same element, in this case `dependency="3"`.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* ### Injecting a directive from a direct parent element
|
* ### Injecting a directive from a direct parent element
|
||||||
*
|
*
|
||||||
* Directives can inject other directives declared on a direct parent element. By definition, a directive with a
|
* Directives can inject other directives declared on a direct parent element. By definition, a directive with a
|
||||||
* `@Parent` annotation does not attempt to resolve dependencies for the current element, even if this would satisfy
|
* `@Parent` annotation does not attempt to resolve dependencies for the current element, even if this would satisfy
|
||||||
* the dependency. [TODO: did I get the subject/verb right?]
|
* the dependency.
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* @Decorator({ selector: '[my-directive]' })
|
* @Decorator({ selector: '[my-directive]' })
|
||||||
|
@ -155,17 +160,15 @@ import {Injectable} from 'angular2/di';
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
* This directive would return `dependency=2` for the example code above. [TODO: True?]
|
* This directive would be instantiated with `Dependency` declared at the parent element, in this case `dependency="2"`.
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* ### Injecting a directive from any ancestor elements
|
* ### Injecting a directive from any ancestor elements
|
||||||
*
|
*
|
||||||
* Directives can inject other directives declared on any ancestor element, i.e. on the parent element and its parents.
|
* Directives can inject other directives declared on any ancestor element (in the current Shadow DOM), i.e. on the
|
||||||
* By definition, a directive with an `@Ancestor` annotation does not attempt to resolve dependencies for the current
|
* parent element and its parents. By definition, a directive with an `@Ancestor` annotation does not attempt to
|
||||||
* element, even if this would satisfy the dependency. [TODO: did I get the subject/verb right? ]
|
* resolve dependencies for the current element, even if this would satisfy the dependency.
|
||||||
*
|
*
|
||||||
* Unlike the `@Parent` which only checks the parent `@Ancestor` checks the parent, as well as its
|
|
||||||
* parents recursivly. If `dependency="2"` would not be present this injection would return `dependency="1"`.
|
|
||||||
|
|
||||||
* ```
|
* ```
|
||||||
* @Decorator({ selector: '[my-directive]' })
|
* @Decorator({ selector: '[my-directive]' })
|
||||||
* class MyDirective {
|
* class MyDirective {
|
||||||
|
@ -175,58 +178,60 @@ import {Injectable} from 'angular2/di';
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* This directive would also return `dependency=2` for the example code above. If `dependency=2` hadn't been declared
|
* Unlike the `@Parent` which only checks the parent, `@Ancestor` checks the parent, as well as its
|
||||||
* on the parent `div`, this directive would return `d[TODO: True?]
|
* parents recursively. If `dependency="2"` didn't exist on the direct parent, this injection would have returned
|
||||||
|
* `dependency="1"`.
|
||||||
*
|
*
|
||||||
* ### Injecting query of child directives. [PENDING IMPLEMENTATION]
|
|
||||||
*
|
*
|
||||||
* In some cases the directive may be interersted in injecting its child directives. This is not directly possible
|
* ### Injecting a live collection of direct child directives [PENDING IMPLEMENTATION]
|
||||||
* since parent directives are guarteed to be created before child directives. Instead we can injecto a container
|
*
|
||||||
* which can than be filled once the data is needed.
|
* A directive can also query for other child directives. Since parent directives are instantiated before child
|
||||||
|
* directives, a directive can't simply inject the list of child directives. Instead, the directive asynchronously
|
||||||
|
* injects a [Query], which updates as children are added, removed, or moved by any [ViewPort] directive such as a
|
||||||
|
* `for`, an `if`, or a `switch`.
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* @Decorator({ selector: '[my-directive]' })
|
* @Decorator({ selector: '[my-directive]' })
|
||||||
* class MyDirective {
|
* class MyDirective {
|
||||||
* constructor(@Children() dependencys:Query<Maker>) {
|
* constructor(@Children() dependencies:Query<Maker>) {
|
||||||
* // dependencys will eventuall contain: [4, 6]
|
|
||||||
* // this will upbate if children are added/removed/moved,
|
|
||||||
* // for example by having for or if.
|
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
* This directive would be instantiated with a [Query] which contains `Dependency` 4 and 6. Here, `Dependency` 5 would
|
||||||
|
* not be included, because it is not a direct child.
|
||||||
*
|
*
|
||||||
* ### Injecting query of descendant directives. [PENDING IMPLEMENTATION]
|
* ### Injecting a live collection of direct descendant directives [PENDING IMPLEMENTATION]
|
||||||
*
|
*
|
||||||
* Similar to `@Children` but also includ childre of those children.
|
* Similar to `@Children` above, but also includes the children of the child elements.
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* @Decorator({ selector: '[my-directive]' })
|
* @Decorator({ selector: '[my-directive]' })
|
||||||
* class MyDirective {
|
* class MyDirective {
|
||||||
* constructor(@Children() dependencys:Query<Maker>) {
|
* constructor(@Children() dependencies:Query<Maker>) {
|
||||||
* // dependencys will eventuall contain: [4, 5, 6]
|
|
||||||
* // this will upbate if children are added/removed/moved,
|
|
||||||
* // for example by having for or if.
|
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
* This directive would be instantiated with a Query which would contain `Dependency` 4, 5 and 6.
|
||||||
*
|
*
|
||||||
* ### Optional injection
|
* ### Optional injection
|
||||||
*
|
*
|
||||||
* Finally there may be times when we would like to inject a component which may or may not be there. For this
|
* The normal behavior of directives is to return an error when a specified dependency cannot be resolved. If you
|
||||||
* use case angular supports `@Optional` injection.
|
* would like to inject `null` on unresolved dependency instead, you can annotate that dependency with `@Optional()`.
|
||||||
|
* This explicitly permits the author of a template to treat some of the surrounding directives as optional.
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* @Decorator({ selector: '[my-directive]' })
|
* @Decorator({ selector: '[my-directive]' })
|
||||||
* class MyDirective {
|
* class MyDirective {
|
||||||
* constructor(@Optional() @Ancestor() form:Form) {
|
* constructor(@Optional() dependency:Dependency) {
|
||||||
* // this will search for a Form directive above itself,
|
|
||||||
* // and inject null if not found
|
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
* This directive would be instantiated with a `Dependency` directive found on the current element. If none can be
|
||||||
|
* found, the injector supplies `null` instead of throwing an error.
|
||||||
|
*
|
||||||
* @publicModule angular2/annotations
|
* @publicModule angular2/annotations
|
||||||
*/
|
*/
|
||||||
@ABSTRACT()
|
@ABSTRACT()
|
||||||
|
@ -235,13 +240,16 @@ export class Directive extends Injectable {
|
||||||
* The CSS selector that triggers the instantiation of a directive.
|
* The CSS selector that triggers the instantiation of a directive.
|
||||||
*
|
*
|
||||||
* Angular only allows directives to trigger on CSS selectors that do not cross element boundaries.
|
* Angular only allows directives to trigger on CSS selectors that do not cross element boundaries.
|
||||||
* The supported selectors are:
|
|
||||||
*
|
*
|
||||||
* - `element-name` select by element name.
|
* `selector` may be declared as one of the following:
|
||||||
* - `.class` select by class name.
|
*
|
||||||
* - `[attribute]` select by attribute name.
|
* - `element-name`: select by element name.
|
||||||
* - `[attribute=value]` select by attribute name and value.
|
* - `.class`: select by class name.
|
||||||
* - `:not(sub_selector)` select only if the element does not match the `sub_selector`.
|
* - `[attribute]`: select by attribute name.
|
||||||
|
* - `[attribute=value]`: select by attribute name and value.
|
||||||
|
* - `:not(sub_selector)`: select only if the element does not match the `sub_selector`.
|
||||||
|
* - `selector1, selector2`: select if either `selector1` or `selector2` matches. [TO BE IMPLMENTED]
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* ## Example
|
* ## Example
|
||||||
*
|
*
|
||||||
|
@ -270,7 +278,8 @@ export class Directive extends Injectable {
|
||||||
* - `bindingProperty` specifies the DOM property where the value is read from.
|
* - `bindingProperty` specifies the DOM property where the value is read from.
|
||||||
*
|
*
|
||||||
* You can include [Pipes] when specifying a `bindingProperty` to allow for data transformation and structural
|
* You can include [Pipes] when specifying a `bindingProperty` to allow for data transformation and structural
|
||||||
* change detection of the value.
|
* change detection of the value. These pipes will be evaluated in the context of this component.
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* ## Syntax
|
* ## Syntax
|
||||||
*
|
*
|
||||||
|
@ -285,43 +294,45 @@ export class Directive extends Injectable {
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* ## Basic Property Binding:
|
* ## Basic Property Binding
|
||||||
|
*
|
||||||
|
* We can easily build a simple `Tooltip` directive that exposes a `tooltip` property, which can be used in templates
|
||||||
|
* with standard Angular syntax. For example:
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* @Decorator({
|
* @Decorator({
|
||||||
* selector: '[tooltip]',
|
* selector: '[tooltip]',
|
||||||
* bind: {
|
* bind: {
|
||||||
* 'tooltipText': 'tooltip'
|
* 'text': 'tooltip'
|
||||||
* }
|
* }
|
||||||
* })
|
* })
|
||||||
* class Tooltip {
|
* class Tooltip {
|
||||||
* set tooltipText(text) {
|
* set text(text) {
|
||||||
* // This will get called every time the 'tooltip' binding changes with the new value.
|
* // This will get called every time the 'tooltip' binding changes with the new value.
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* As used in this example:
|
* We can then bind to the `tooltip' property as either an expression (`someExpression`) or as a string literal, as
|
||||||
|
* shown in the HTML template below:
|
||||||
*
|
*
|
||||||
* ```html
|
* ```html
|
||||||
* <div [tooltip]="someExpression">
|
* <div [tooltip]="someExpression">...</div>
|
||||||
|
* <div tooltip="Some Text">...</div>
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Whenever the `someExpression` expression changes, the `bind` declaration instructs Angular to update the
|
* Whenever the `someExpression` expression changes, the `bind` declaration instructs Angular to update the
|
||||||
* `Tooltip`'s `tooltipText` property.
|
* `Tooltip`'s `tooltipText` property.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Similarly in this example:
|
|
||||||
*
|
|
||||||
* ```html
|
|
||||||
* <div tooltip="Some Text">
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* The `Tooltip`'s `tooltipText` property gets initialized to the `Some Text` literal.
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
* ## Bindings With Pipes:
|
* ## Bindings With Pipes:
|
||||||
*
|
*
|
||||||
|
* You can also use pipes when writing binding definitions for a directive.
|
||||||
|
*
|
||||||
|
* For example, we could write a binding that updates the directive on structural changes, rather than on reference
|
||||||
|
* changes, as normally occurs in change detection. (See: [Pipe] and [keyValueDiff] documentaition for more details.)
|
||||||
|
*
|
||||||
* ```
|
* ```
|
||||||
* @Decorator({
|
* @Decorator({
|
||||||
* selector: '[class-set]',
|
* selector: '[class-set]',
|
||||||
|
@ -336,29 +347,30 @@ export class Directive extends Injectable {
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* As used in this example:
|
* The template that this directive is used in may also contain its own pipes. For example:
|
||||||
*
|
*
|
||||||
* ```html
|
* ```html
|
||||||
* <div [class-set]="someExpression">
|
* <div [class-set]="someExpression | somePipe">
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* In the above example, the `ClassSet` uses the `keyValDiff` [Pipe] for watching structural changes. This means that
|
* In this case, the two pipes compose as if they were inlined: `someExpression | somePipe | keyValDiff`.
|
||||||
* the `classChanges` setter gets invoked if the expression changes to a different reference, or if the
|
|
||||||
* structure of the expression changes. (Shallow property watching of the object)
|
|
||||||
*
|
|
||||||
* NOTE: The `someExpression` can also contain its own [Pipe]s. In this case, the two pipes compose as if they were
|
|
||||||
* inlined.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bind:any; // StringMap
|
bind:any; // StringMap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies which DOM events the directive listens to and what the action should be when they occur.
|
* Specifies which DOM events a directive listens to.
|
||||||
*
|
*
|
||||||
* The `events` property defines a set of `event` to `method` key-value pairs:
|
* The `events` property defines a set of `event` to `method` key-value pairs:
|
||||||
*
|
*
|
||||||
* - `event1` specifies the DOM event that the directive listens to.
|
* - `event1`: the DOM event that the directive listens to.
|
||||||
* - `onMethod1` specifies the method to execute when the event occurs.
|
* - `statement`: the statment to execute when the event occurs.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* When writing a directive event binding, you can also refer to the following local variables:
|
||||||
|
* - `$event`: Current event object which triggerd the event.
|
||||||
|
* - `$target`: The source of the event. This will be either a DOM element or an Angular directive.
|
||||||
|
* [TO BE IMPLEMENTED]
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* ## Syntax
|
* ## Syntax
|
||||||
|
@ -366,7 +378,7 @@ export class Directive extends Injectable {
|
||||||
* ```
|
* ```
|
||||||
* @Directive({
|
* @Directive({
|
||||||
* events: {
|
* events: {
|
||||||
* 'event1': 'onMethod1',
|
* 'event1': 'onMethod1(arguments)',
|
||||||
* ...
|
* ...
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
|
@ -374,20 +386,24 @@ export class Directive extends Injectable {
|
||||||
*
|
*
|
||||||
* ## Basic Event Binding:
|
* ## Basic Event Binding:
|
||||||
*
|
*
|
||||||
|
* Suppose you want to write a directive that triggers on `change` events in the DOM. You would define the event
|
||||||
|
* binding as follows:
|
||||||
|
*
|
||||||
* ```
|
* ```
|
||||||
* @Decorator({
|
* @Decorator({
|
||||||
* selector: 'input',
|
* selector: 'input',
|
||||||
* events: {
|
* events: {
|
||||||
* 'change': 'onChange'
|
* 'change': 'onChange($event)'
|
||||||
* }
|
* }
|
||||||
* })
|
* })
|
||||||
* class InputDecorator {
|
* class InputDecorator {
|
||||||
* onChange(event:Event) {
|
* onChange(event:Event) {
|
||||||
* // invoked whenever the DOM element fires the 'change' event.
|
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
* Here `InputDecorator` is invoked whenever the DOM element fires the 'change' event.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
events:any; // StringMap
|
events:any; // StringMap
|
||||||
|
|
||||||
|
@ -420,6 +436,8 @@ export class Directive extends Injectable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if a directive participates in a given [LifecycleEvent].
|
* Returns true if a directive participates in a given [LifecycleEvent].
|
||||||
|
*
|
||||||
|
* See: [onChange], [onDestroy] for details.
|
||||||
*/
|
*/
|
||||||
hasLifecycleHook(hook:string):boolean {
|
hasLifecycleHook(hook:string):boolean {
|
||||||
return isPresent(this.lifecycle) ? ListWrapper.contains(this.lifecycle, hook) : false;
|
return isPresent(this.lifecycle) ? ListWrapper.contains(this.lifecycle, hook) : false;
|
||||||
|
@ -427,21 +445,29 @@ export class Directive extends Injectable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Components are angular directives with Shadow DOM views.
|
* Declare template views for an Angular application.
|
||||||
*
|
*
|
||||||
* Componests are used to encapsulate state and template into reusable building blocks. An angular component requires
|
* Each angular component requires a single `@Component` and at least one `@Template` annotation. This allows Angular to
|
||||||
* an `@Component` and at least one `@Template` annotation (see [Template] for more datails.) Components instances are
|
* encapsulate state information and templates. These form the fundamental reusable building blocks for developing an
|
||||||
* used as the context for evaluation of the Shadow DOM view.
|
* application. There can only be one component per DOM element.
|
||||||
*
|
*
|
||||||
* Restrictions:
|
* When a component is instantiated, Angular
|
||||||
* - Thre can anly be one component per DOM element.
|
* - creates a shadow DOM for the component.
|
||||||
|
* - loads the selected template into the shadow DOM.
|
||||||
|
* - creates a child [Injector] which is configured with the [Component.services].
|
||||||
|
*
|
||||||
|
* All template expressions and statments are then evaluted against the component instance.
|
||||||
|
*
|
||||||
|
* For details on the `@Template` annotation, see [Template].
|
||||||
*
|
*
|
||||||
* ## Example
|
* ## Example
|
||||||
|
*
|
||||||
|
* ```
|
||||||
* @Component({
|
* @Component({
|
||||||
* selector: 'greet'
|
* selector: 'greet'
|
||||||
* })
|
* })
|
||||||
* @Template({
|
* @Template({
|
||||||
* inline: 'Hello {{name}}'
|
* inline: 'Hello {{name}}!'
|
||||||
* })
|
* })
|
||||||
* class Greet {
|
* class Greet {
|
||||||
* name: string;
|
* name: string;
|
||||||
|
@ -450,75 +476,56 @@ export class Directive extends Injectable {
|
||||||
* this.name = 'World';
|
* this.name = 'World';
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
|
* ```
|
||||||
*
|
*
|
||||||
* @publicModule angular2/annotations
|
* @publicModule angular2/annotations
|
||||||
*/
|
*/
|
||||||
export class Component extends Directive {
|
export class Component extends Directive {
|
||||||
/**
|
/**
|
||||||
* Defines the set of injectables that are visible to a Component and its children.
|
* Defines the set of injectable objects that are visible to a Component and its children.
|
||||||
*
|
*
|
||||||
* When a [Component] defines [injectables], Angular creates a new application-level [Injector] for the component
|
* The [services] defined in the Component annotation allow you to configure a set of bindings for the component's
|
||||||
* and its children. Injectables are defined as a list of [Binding]s, (or as [Type]s as short hand). These bindings
|
* injector.
|
||||||
* are passed to the [Injector] constructor when making a new child [Injector]. The injectables are available for
|
|
||||||
* all child directives of the Component (but not the declaring component's light DOM directives).
|
|
||||||
*
|
*
|
||||||
* ## Example
|
* When a component is instantiated, Angular creates a new child Injector, which is configured with the bindings in
|
||||||
* // Example of a class which we would like to inject.
|
* the Component [services] annotation. The injectable objects then become available for injection to the component
|
||||||
|
* itself and any of the directives in the component's template, i.e. they are not available to the directives which
|
||||||
|
* are children in the component's light DOM.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The syntax for configuring the [services] injectable is identical to [Injector] injectable configuration. See
|
||||||
|
* [Injector] for additional detail.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ## Simple Example
|
||||||
|
*
|
||||||
|
* Here is an example of a class that can be injected:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
* class Greeter {
|
* class Greeter {
|
||||||
* salutation:string;
|
|
||||||
*
|
|
||||||
* constructor(salutation:string) {
|
|
||||||
* this.salutation = salutation;
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* greet(name:string) {
|
* greet(name:string) {
|
||||||
* return this.salutation + ' ' + name + '!';
|
* return 'Hello ' + name + '!';
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* @Component({
|
* @Component({
|
||||||
* selector: 'greet',
|
* selector: 'greet',
|
||||||
* services: [
|
* services: [
|
||||||
* bind(String).toValue('Hello'), // Configure injection of string
|
* Greeter
|
||||||
* Greeter // Make Greeter available for injection
|
|
||||||
* ]
|
* ]
|
||||||
* })
|
* })
|
||||||
* @Template({
|
* @Template({
|
||||||
* inline: '<child></child>',
|
* inline: `{{greeter.greet('world')}}!`,
|
||||||
* directives: Child
|
* directives: Child
|
||||||
* })
|
* })
|
||||||
* class Greet {
|
* class HelloWorld {
|
||||||
* greeter: Greeter;
|
* greeter:Greeter;
|
||||||
*
|
*
|
||||||
* constructor(greeter: Greeter) {
|
* constructor(greeter:Greeter) {
|
||||||
* // Greeter can be injected here becouse it was declared as injectable
|
|
||||||
* // in this component, or parent component.
|
|
||||||
* this.greeter = greeter;
|
* this.greeter = greeter;
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*
|
* ```
|
||||||
* @Decorator({
|
|
||||||
* selector: 'child'
|
|
||||||
* })
|
|
||||||
* class Child {
|
|
||||||
* greeter: Greeter;
|
|
||||||
*
|
|
||||||
* constructor(greeter: Greeter) {
|
|
||||||
* // Greeter can be injected here becouse it was declared as injectable
|
|
||||||
* // in a an ancestor component.
|
|
||||||
* this.greeter = greeter;
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Let's look at the [services] part of the example above.
|
|
||||||
*
|
|
||||||
* services: [
|
|
||||||
* bind(String).toValue('Hello'),
|
|
||||||
* Greeter
|
|
||||||
* ]
|
|
||||||
*
|
|
||||||
* Here the `Greeter` is a short hand for `bind(Greeter).toClass(Greeter)`. See [bind] DSL for more details.
|
|
||||||
*/
|
*/
|
||||||
services:List;
|
services:List;
|
||||||
|
|
||||||
|
@ -549,24 +556,31 @@ export class Component extends Directive {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DynamicComponents allow loading child components impretivly.
|
* A directive used for dynamically loading components.
|
||||||
*
|
*
|
||||||
* A Component can be made of other compontents. This recursive nature must be resolved synchronously during the
|
* Regular angular components are statically resolved. DynamicComponent allows to you resolve a component at runtime
|
||||||
* component template processing. This means that all templates are resolved synchronously. This prevents lazy loading
|
* instead by providing a placeholder into which a regular angular component can be dynamically loaded. Once loaded,
|
||||||
* of code or delayed binding of views to the components.
|
* the dynamically-loaded component becomes permanent and cannot be changed.
|
||||||
*
|
|
||||||
* A DynamicComponent is a placeholder into which a regular component can be loaded imperativly and thus breaking
|
|
||||||
* the all components must be resolved synchronously restriction. Once loaded the component is premanent.
|
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* ## Example
|
* ## Example
|
||||||
|
*
|
||||||
|
* Here we have `DynamicComp` which acts as the placeholder for `HelloCmp`. At runtime, the dynamic component
|
||||||
|
* `DynamicComp` requests loading of the `HelloCmp` component.
|
||||||
|
*
|
||||||
|
* There is nothing special about `HelloCmp`, which is a regular angular component. It can also be used in other static
|
||||||
|
* locations.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
* @DynamicComponent({
|
* @DynamicComponent({
|
||||||
* selector: 'dynamic-comp'
|
* selector: 'dynamic-comp'
|
||||||
* })
|
* })
|
||||||
* class DynamicComp {
|
* class DynamicComp {
|
||||||
* done;
|
* helloCmp:HelloCmp;
|
||||||
* constructor(loader:PrivateComponentLoader, location:PrivateComponentLocation) {
|
* constructor(loader:PrivateComponentLoader, location:PrivateComponentLocation) {
|
||||||
* this.done = loader.load(HelloCmp, location);
|
* loader.load(HelloCmp, location).then((helloCmp) => {
|
||||||
|
* this.helloCmp = helloCmp;
|
||||||
|
* });
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
|
@ -582,11 +596,17 @@ export class Component extends Directive {
|
||||||
* this.greeting = "hello";
|
* this.greeting = "hello";
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @publicModule angular2/annotations
|
* @publicModule angular2/annotations
|
||||||
*/
|
*/
|
||||||
export class DynamicComponent extends Directive {
|
export class DynamicComponent extends Directive {
|
||||||
|
/**
|
||||||
|
* Same as [Component.services].
|
||||||
|
*/
|
||||||
|
// TODO(vsankin): Please extract into AbstractComponent
|
||||||
services:any; //List;
|
services:any; //List;
|
||||||
|
|
||||||
@CONST()
|
@CONST()
|
||||||
|
@ -615,26 +635,24 @@ export class DynamicComponent extends Directive {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decorators allow attaching behavior to DOM elements in a composable manner.
|
* Directive that attaches behavior to DOM elements.
|
||||||
|
*
|
||||||
|
* A decorator directive attaches behavior to a DOM element in a composable manner.
|
||||||
|
* (see: http://en.wikipedia.org/wiki/Composition_over_inheritance)
|
||||||
*
|
*
|
||||||
* Decorators:
|
* Decorators:
|
||||||
* - are simplest form of [Directive]s.
|
* - are simplest form of [Directive]s.
|
||||||
* - are besed used as compostinion pattern ()
|
* - are best used as a composition pattern ()
|
||||||
*
|
*
|
||||||
* Decoraters differ from [Component]s in that they:
|
* Decorators differ from [Component]s in that they:
|
||||||
* - can have any number of decorators per element
|
* - can have multiple decorators per element
|
||||||
* - do not create their own evaluation context
|
* - do not create their own evaluation context
|
||||||
* - do not have template (and therefor do not create Shadow DOM)
|
* - do not have template (and therefor do not create Shadow DOM)
|
||||||
*
|
*
|
||||||
|
*
|
||||||
* ## Example
|
* ## Example
|
||||||
*
|
*
|
||||||
* Let's say we would like to add tool-tip behavior to any alement.
|
* Here we use a decorator directive to simply define basic tool-tip behavior.
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* <div tooltip="some text here"></div>
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* We could have a decorator directive like so:
|
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* @Decorator({
|
* @Decorator({
|
||||||
|
@ -643,8 +661,8 @@ export class DynamicComponent extends Directive {
|
||||||
* 'text': 'tooltip'
|
* 'text': 'tooltip'
|
||||||
* },
|
* },
|
||||||
* event: {
|
* event: {
|
||||||
* 'onmouseenter': 'onMouseEnter',
|
* 'onmouseenter': 'onMouseEnter()',
|
||||||
* 'onmouseleave': 'onMouseLeave'
|
* 'onmouseleave': 'onMouseLeave()'
|
||||||
* }
|
* }
|
||||||
* })
|
* })
|
||||||
* class Tooltip{
|
* class Tooltip{
|
||||||
|
@ -667,10 +685,23 @@ export class DynamicComponent extends Directive {
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
|
* In our HTML template, we can then add this behavior to a `<div>` or any other element with the `tooltip` selector,
|
||||||
|
* like so:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <div tooltip="some text here"></div>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
* @publicModule angular2/annotations
|
* @publicModule angular2/annotations
|
||||||
*/
|
*/
|
||||||
export class Decorator extends Directive {
|
export class Decorator extends Directive {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to true the compiler does not compile the children of this directive.
|
||||||
|
*/
|
||||||
|
//TODO(vsavkin): This would better fall under the Macro directive concept.
|
||||||
compileChildren: boolean;
|
compileChildren: boolean;
|
||||||
|
|
||||||
@CONST()
|
@CONST()
|
||||||
constructor({
|
constructor({
|
||||||
selector,
|
selector,
|
||||||
|
@ -697,10 +728,12 @@ export class Decorator extends Directive {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Viewport is used for controlling the instatiation of inline templates.
|
* Viewport is used for controlling the instatiation of inline templates. [TODO: needs co-work :)]
|
||||||
*
|
*
|
||||||
* Viewport consist of a controller which can inject [ViewContainer]. A [ViewContainer] rerpsents a location in the
|
* Viewport consist of a controller which can inject [ViewContainer]. A [ViewContainer] represents a location in the
|
||||||
* current view where child views can be inserted.
|
* current view where child views can be inserted. [ViewContainer] is created as a result of `<template>` element.
|
||||||
|
*
|
||||||
|
* NOTE: `<template>` directives can be created in shorthand form as `<TAG template="...">` or `<TAG *key="...">`
|
||||||
*
|
*
|
||||||
* ## Example
|
* ## Example
|
||||||
*
|
*
|
||||||
|
@ -742,6 +775,34 @@ export class Decorator extends Directive {
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
* To better undarstand what is hapening, remember that angular converts the above template to:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <ul>
|
||||||
|
* <template [unless]="exp">
|
||||||
|
* <li></li>
|
||||||
|
* </template>
|
||||||
|
* </ul>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Notice that the `*unless="exp"` got hoisted to `<template>`. This means that the `Viewport` controller is instantiated
|
||||||
|
* on the `<template>` element rather thna the `<li>` element.
|
||||||
|
*
|
||||||
|
* Once the viewport insntantiates the child view the result is:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <ul>
|
||||||
|
* <template [unless]="exp">
|
||||||
|
* <li></li>
|
||||||
|
* </template>
|
||||||
|
* <li></li>
|
||||||
|
* </ul>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The key thing to notice here is that `<li>` instance is a sibling of `<template>` not a child. For this reason
|
||||||
|
* it is not possible to inject `Viewport` directive into other directives, (`Viweport` directives are always on
|
||||||
|
* `<template>` elements which are leafs.)
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* @publicModule angular2/annotations
|
* @publicModule angular2/annotations
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {ABSTRACT, CONST, Type} from 'angular2/src/facade/lang';
|
import {ABSTRACT, CONST, Type} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @publicModule angular2/angular2
|
* @publicModule angular2/annotations
|
||||||
*/
|
*/
|
||||||
export class Template {
|
export class Template {
|
||||||
url:any; //string;
|
url:any; //string;
|
||||||
|
|
|
@ -2,8 +2,40 @@ import {CONST} from 'angular2/src/facade/lang';
|
||||||
import {DependencyAnnotation} from 'angular2/di';
|
import {DependencyAnnotation} from 'angular2/di';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The directive can only be injected from the current element
|
* The directive can only be injected from the parent element.
|
||||||
* or from its parent.
|
*
|
||||||
|
* ## Example
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <div dependency="1">
|
||||||
|
* <div dependency="2" my-directive></div>
|
||||||
|
* </div>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* @Decorator({
|
||||||
|
* selector: '[dependency]',
|
||||||
|
* bind: {
|
||||||
|
* 'id':'dependency'
|
||||||
|
* }
|
||||||
|
* })
|
||||||
|
* class Dependency {
|
||||||
|
* id:string;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @Decorator({
|
||||||
|
* selector: '[my-directive]'
|
||||||
|
* })
|
||||||
|
* class Dependency {
|
||||||
|
* constructor(@Parent() dependency:Dependency) {
|
||||||
|
* expect(dependency.id).toEqual(1);
|
||||||
|
* };
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* In the above example the `@Parent()` annotation forces the injector to retrieve the dependency from the
|
||||||
|
* parent element (even thought the current element could resolve it).
|
||||||
*
|
*
|
||||||
* @publicModule angular2/annotations
|
* @publicModule angular2/annotations
|
||||||
*/
|
*/
|
||||||
|
@ -15,8 +47,48 @@ export class Parent extends DependencyAnnotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The directive can only be injected from the current element
|
* The directive can only be injected from the ancestor (any element between parent element and shadow root).
|
||||||
* or from its ancestor.
|
*
|
||||||
|
*
|
||||||
|
* ## Example
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <div dependency="1">
|
||||||
|
* <div dependency="2">
|
||||||
|
* <div>
|
||||||
|
* <div dependency="3" my-directive></div>
|
||||||
|
* </div>
|
||||||
|
* </div>
|
||||||
|
* </div>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* @Decorator({
|
||||||
|
* selector: '[dependency]',
|
||||||
|
* bind: {
|
||||||
|
* 'id':'dependency'
|
||||||
|
* }
|
||||||
|
* })
|
||||||
|
* class Dependency {
|
||||||
|
* id:string;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @Decorator({
|
||||||
|
* selector: '[my-directive]'
|
||||||
|
* })
|
||||||
|
* class Dependency {
|
||||||
|
* constructor(@Ancestor() dependency:Dependency) {
|
||||||
|
* expect(dependency.id).toEqual(2);
|
||||||
|
* };
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* In the above example the `@Ancestor()` annotation forces the injector to retrieve the dependency from the
|
||||||
|
* first ancestor.
|
||||||
|
* - The current element `dependency="3"` is skipped
|
||||||
|
* - Next parent has no directives `<div>`
|
||||||
|
* - Next parent has the `Dependency` directive and so the dependency is satisfied.
|
||||||
*
|
*
|
||||||
* @publicModule angular2/annotations
|
* @publicModule angular2/annotations
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue