From 51ada60d91c913861eebc7ff8bbc7c70f5fd8e7c Mon Sep 17 00:00:00 2001 From: Alex Wolfe Date: Mon, 13 Apr 2015 06:53:38 -0700 Subject: [PATCH] api example formatted --- .../docs/js/latest/api/annotations/_data.json | 5 + .../api/annotations/directive-class.jade | 315 ++++++++++++++++++ 2 files changed, 320 insertions(+) create mode 100644 public/docs/js/latest/api/annotations/_data.json create mode 100644 public/docs/js/latest/api/annotations/directive-class.jade diff --git a/public/docs/js/latest/api/annotations/_data.json b/public/docs/js/latest/api/annotations/_data.json new file mode 100644 index 0000000000..eff4776dad --- /dev/null +++ b/public/docs/js/latest/api/annotations/_data.json @@ -0,0 +1,5 @@ +{ + "directive-class": { + "title": "Directive Class" + } +} diff --git a/public/docs/js/latest/api/annotations/directive-class.jade b/public/docs/js/latest/api/annotations/directive-class.jade new file mode 100644 index 0000000000..6410da23c8 --- /dev/null +++ b/public/docs/js/latest/api/annotations/directive-class.jade @@ -0,0 +1,315 @@ +p. + Directives allow you to attach behavior to elements in the DOM. + Directive is an abstract concept, instead use concrete directives: [Component], [DynamicComponent], [Decorator] or [Viewport]. + A directive consists of a single directive annotation and a controller class. When the directive's [selector] matches elements in the DOM, the following steps occur: + +p. + For each directive, the [ElementInjector] attempts to resolve the directive's constructor arguments. + Angular instantiates directives for each matched element using [ElementInjector] in a depth-first order, as declared in the HTML. + +.l-main-section + + h2 Understanding How Injection Works + + p There are three stages of injection resolution. + + dl + dt Pre-existing Injectors: + dd + ul + li The terminal [Injector] cannot resolve dependencies. It either throws an error or, if the dependency was specified as @Optional, returns null. + li The primordial injector resolves browser singleton resources, such as: cookies, title, location, and others. + + dt Component Injectors: + dd Each @Component has its own [Injector], and they follow the same parent-child hierarchy as the components in the DOM. + + dt Element Injectors: + dd Each component has a Shadow DOM. Within the Shadow DOM each element has an [ElementInjector] which follow the same parent-child hierarchy as the DOM elements themselves. + + + p When a template is instantiated, it also must instantiate the corresponding directives in a depth-first order. The current [ElementInjector] resolves the constructor dependencies for each directive. + + p Angular then resolves dependencies as follows, according to the order in which they appear in the [View]: + + ol + li Dependencies on the current element + li Dependencies on element injectors and their parents until it encounters a Shadow DOM boundary + li Dependencies on component injectors and their parents until it encounters the root component + li Dependencies on pre-existing injectors + + p The [ElementInjector] can inject other directives, element-specific special objects, or it can delegate to the parent injector. + + p To inject other directives, declare the constructor parameter as: + + ul + li directive:DirectiveType: a directive on the current element only + li @Ancestor() directive:DirectiveType: any directive that matches the type between the current element and the Shadow DOM root. Current element is not included in the resolution, therefor even if it could resolve it, it will be ignored. + li @Parent() directive:DirectiveType: any directive that matches the type on a direct parent element only. + li @Children query:Query: A live collection of direct child directives [TO BE IMPLEMENTED]. + li @Descendants query:Query: A live collection of any child directives [TO BE IMPLEMENTED]. + + p To inject element-specific special objects, declare the constructor parameter as: + + ul + li element: NgElement to obtain a DOM element (DEPRECATED: replacement coming) + li viewContainer: ViewContainer to control child template instantiation, for [Viewport] directives only + li bindingPropagation: BindingPropagation to control change detection in a more granular way. + +.l-main-section + h2 Example of Injection + + p The following example demonstrates how dependency injection resolves constructor arguments in practice. + + p Assume this HTML template: + + pre.prettyprint.linenums.lang-html + code. + <div dependency="1"> + <div dependency="2"> + <div dependency="3" my-directive> + <div dependency="4"> + <div dependency="5"></div> + </div> + <div dependency="6"></div> + </div> + </div> + </div> + + p With the following dependency decorator and SomeService injectable class. + + pre.prettyprint.linenums + code. + @Injectable() + class SomeService { + } + + @Decorator({ + selector: '[dependency]', + bind: { + 'id':'dependency' + } + }) + class Dependency { + id:string; + } + + p Let's step through the different ways in which MyDirective could be declared... + + .l-sub-section + h3 No injection + + p Here the constructor is declared with no arguments, therefore nothing is injected into MyDirective. + + pre.prettyprint.linenums + code. + @Decorator({ selector: '[my-directive]' }) + class MyDirective { + constructor() { + } + } + + p This directive would be instantiated with no dependencies. + + .l-sub-section + h3 Component-level injection + + p Directives can inject any injectable instance from the closest component injector or any of its parents. + + p Here, the constructor declares a parameter, someService, and injects the SomeService type from the parent component's injector. + + pre.prettyprint.linenums + code. + @Decorator({ selector: '[my-directive]' }) + class MyDirective { + constructor(someService: SomeService) { + } + } + + p This directive would be instantiated with a dependency on SomeService. + + + .l-sub-section + h3 Injecting a directive from the current element + + p Directives can inject other directives declared on the current element. + + pre.prettyprint.linenums + code. + @Decorator({ selector: '[my-directive]' }) + class MyDirective { + constructor(dependency: Dependency) { + expect(dependency.id).toEqual(3); + } + } + + p This directive would be instantiated with Dependency declared at the same element, in this case dependency="3". + + + .l-sub-section + h3 Injecting a directive from a direct parent element + + p 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 the dependency. + + pre.prettyprint.linenums + code. + @Decorator({ selector: '[my-directive]' }) + class MyDirective { + constructor(@Parent() dependency: Dependency) { + expect(dependency.id).toEqual(2); + } + } + + p This directive would be instantiated with Dependency declared at the parent element, in this case dependency="2". + + .l-sub-section + h3 Injecting a directive from any ancestor elements + + p Directives can inject other directives declared on any ancestor element (in the current Shadow DOM), i.e. on the parent element and its parents. By definition, a directive with an @Ancestor annotation does not attempt to resolve dependencies for the current element, even if this would satisfy the dependency. + + pre.prettyprint.linenums + code. + @Decorator({ selector: '[my-directive]' }) + class MyDirective { + constructor(@Ancestor() dependency: Dependency) { + expect(dependency.id).toEqual(2); + } + } + + p Unlike the @Parent which only checks the parent, @Ancestor checks the parent, as well as its parents recursively. If dependency="2" didn't exist on the direct parent, this injection would have returned dependency="1". + + .l-sub-section + h3 Injecting a live collection of direct child directives [PENDING IMPLEMENTATION] + p 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. + + pre.prettyprint.linenums + code. + @Decorator({ selector: '[my-directive]' }) + class MyDirective { + constructor(@Children() dependencies:Query) { + } + } + + p. 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. + + .l-sub-section + h3 Injecting a live collection of direct descendant directives [PENDING IMPLEMENTATION] + + p Similar to @Children above, but also includes the children of the child elements. + + pre.prettyprint.linenums + code. + @Decorator({ selector: '[my-directive]' }) + class MyDirective { + constructor(@Children() dependencies:Query) { + } + } + + p This directive would be instantiated with a Query which would contain Dependency 4, 5 and 6. + + .l-sub-section + h3 Optional injection + + p The normal behavior of directives is to return an error when a specified dependency cannot be resolved. If you 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. + + pre.prettyprint.linenums + code. + @Decorator({ selector: '[my-directive]' }) + class MyDirective { + constructor(@Optional() dependency:Dependency) { + } + } + + p 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. + +.l-main-section + + h2 Members + + p + strong constructor({ selector, bind, events, lifecycle }:{ selector:string, bind:any, events: any, lifecycle:List }={}) + + .l-sub-section + h3 bind + + p Enumerates the set of properties that accept data binding for a directive. + + p The bind property defines a set of directiveProperty to bindingProperty key-value pairs: + + ul + li directiveProperty specifies the component property where the value is written. + li bindingProperty specifies the DOM property where the value is read from. + + p You can include [Pipes] when specifying a bindingProperty to allow for data transformation and structural change detection of the value. These pipes will be evaluated in the context of this component. + + +.l-main-section + h2 Syntax + + pre.prettyprint.linenums + code. + @Directive({ + bind: { + 'directiveProperty1': 'bindingProperty1', + 'directiveProperty2': 'bindingProperty2 | pipe1 | ...', + ... + } + } + +.l-main-section + h2 Basic Property Binding + + p 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: + + pre.prettyprint.linenums + code. + @Decorator({ + selector: '[tooltip]', + bind: { + 'text': 'tooltip' + } + }) + class Tooltip { + set text(text) { + // This will get called every time the 'tooltip' binding changes with the new value. + } + } + + p 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: + + pre.prettyprint.linenums + code. + <div [tooltip]="someExpression">...</div> + <div tooltip="Some Text">...</div> + + p Whenever the someExpression expression changes, the bind declaration instructs Angular to update the Tooltip's text property. + +.l-main-section + h2 Bindings With Pipes + + p You can also use pipes when writing binding definitions for a directive. + + p 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] documentation for more details.) + + pre.prettyprint.linenums + code. + @Decorator({ + selector: '[class-set]', + bind: { + 'classChanges': 'classSet | keyValDiff' + } + }) + class ClassSet { + set classChanges(changes:KeyValueChanges) { + // This will get called every time the `class-set` expressions changes its structure. + } + } + + p The template that this directive is used in may also contain its own pipes. For example: + + pre.prettyprint.linenums + code. + <div [class-set]="someExpression | somePipe"> + + p In this case, the two pipes compose as if they were inlined: someExpression | somePipe | keyValDiff. + +.location-badge exported from angular2/annotations \ No newline at end of file