diff --git a/public/_includes/_util-fns.jade b/public/_includes/_util-fns.jade index cf1090a6a5..0bb81db082 100644 --- a/public/_includes/_util-fns.jade +++ b/public/_includes/_util-fns.jade @@ -1,11 +1,28 @@ //- Mixins and associated functions -- var _docsFor = 'ts'; // or 'dart' or 'js'. +//- _docsFor: used to identify the language this version of the docs if for; +//- Should be one of: 'ts', 'dart' or 'js'. Set in lang specific _util-fns file. +- var _docsFor = ''; +//- Simple "macros" used via interpolation in text: +//- e.g., the #{_priv}el variable has an `@Input` #{_decorator}. + +//- Use #{_decorator} whereever the word "decorator" is expected, provided it is not +//- preceded by the article "a". (E.g., will be "annotation" for Dart) +- var _decorator = 'decorator'; + +//- Used to prefix identifiers that are private. In Dart this will be '_'. +- var _priv = ''; + +//- Use to conditionally include the block that follows +ifDocsFor(...). +//- Generally favor use of Jade named blocks instead. ifDocsFor is convenient +//- for prose that should appear only in one language version. mixin ifDocsFor(lang) if _docsFor.toLowerCase() === lang.toLowerCase() block +//- Use to map inlined (prose) TS paths into, say, Dart paths via the +//- adjustExamplePath transformer function. mixin adjExPath(path) if adjustExamplePath | #{adjustExamplePath(path)} diff --git a/public/docs/_examples/attribute-directives/dart/lib/app_component.dart b/public/docs/_examples/attribute-directives/dart/lib/app_component.dart index 2494fc3fd7..29f44ea6e9 100644 --- a/public/docs/_examples/attribute-directives/dart/lib/app_component.dart +++ b/public/docs/_examples/attribute-directives/dart/lib/app_component.dart @@ -6,7 +6,7 @@ import 'highlight_directive.dart'; @Component( selector: 'my-app', templateUrl: 'app_component.html', - directives: const [Highlight]) + directives: const [HighlightDirective]) class AppComponent { String color; } diff --git a/public/docs/_examples/attribute-directives/dart/lib/app_component.html b/public/docs/_examples/attribute-directives/dart/lib/app_component.html index b8fd63c8e3..f174bebbbb 100644 --- a/public/docs/_examples/attribute-directives/dart/lib/app_component.html +++ b/public/docs/_examples/attribute-directives/dart/lib/app_component.html @@ -7,14 +7,14 @@ Yellow Cyan - -

Highlight me!

- + +

Highlight me!

+ -

+

Highlight me too! -

+

diff --git a/public/docs/_examples/attribute-directives/dart/lib/app_component_1.html b/public/docs/_examples/attribute-directives/dart/lib/app_component_1.html index b76a260a1a..ef66580027 100644 --- a/public/docs/_examples/attribute-directives/dart/lib/app_component_1.html +++ b/public/docs/_examples/attribute-directives/dart/lib/app_component_1.html @@ -1,3 +1,3 @@

My First Attribute Directive

-Highlight me! +

Highlight me!

diff --git a/public/docs/_examples/attribute-directives/dart/lib/highlight_directive.dart b/public/docs/_examples/attribute-directives/dart/lib/highlight_directive.dart index a6c0856cc4..e6190a443c 100644 --- a/public/docs/_examples/attribute-directives/dart/lib/highlight_directive.dart +++ b/public/docs/_examples/attribute-directives/dart/lib/highlight_directive.dart @@ -2,51 +2,42 @@ // #docregion full import 'package:angular2/core.dart'; -@Directive(selector: '[my-highlight]', host: const { +@Directive(selector: '[myHighlight]', host: const { '(mouseenter)': 'onMouseEnter()', '(mouseleave)': 'onMouseLeave()' }) // #docregion class-1 -class Highlight { - // #enddocregion class-1 -// #enddocregion full - /* -// #docregion highlight - @Input() myHighlight: string; -// #enddocregion highlight - */ -// #docregion full -// #docregion class-1 -// #docregion color - @Input('my-highlight') String highlightColor; -// #enddocregion color - +class HighlightDirective { String _defaultColor = 'red'; + final dynamic _el; + + HighlightDirective(ElementRef elRef) : _el = elRef.nativeElement; // #enddocregion class-1 + // #docregion defaultColor @Input() set defaultColor(String colorName) { _defaultColor = (colorName ?? _defaultColor); } // #enddocregion defaultColor -// #docregion class-1 + // #docregion class-1 - final ElementRef _element; + // #docregion color + @Input('myHighlight') String highlightColor; + // #enddocregion color + + // #docregion mouse-enter + void onMouseEnter() { _highlight(highlightColor ?? _defaultColor); } + // #enddocregion mouse-enter + void onMouseLeave() { _highlight(); } -// #docregion mouse-enter - onMouseEnter() { - _highlight(highlightColor ?? _defaultColor); + void _highlight([String color]) { + if(_el != null) _el.style.backgroundColor = color; } - -// #enddocregion mouse-enter - onMouseLeave() { - _highlight(null); - } - - void _highlight(String color) { - _element.nativeElement.style.backgroundColor = color; - } - - Highlight(this._element); } // #enddocregion class-1 // #enddocregion full +/* +// #docregion highlight +@Input() String myHighlight; +// #enddocregion highlight +*/ diff --git a/public/docs/_examples/attribute-directives/dart/lib/highlight_directive_1.dart b/public/docs/_examples/attribute-directives/dart/lib/highlight_directive_1.dart index 3b79e66a3b..2ce0e35919 100644 --- a/public/docs/_examples/attribute-directives/dart/lib/highlight_directive_1.dart +++ b/public/docs/_examples/attribute-directives/dart/lib/highlight_directive_1.dart @@ -3,9 +3,9 @@ library attribute_directives.highlight_directive; import 'package:angular2/core.dart'; -@Directive(selector: '[my-highlight]') -class Highlight { - Highlight(ElementRef element) { +@Directive(selector: '[myHighlight]') +class HighlightDirective { + HighlightDirective(ElementRef element) { element.nativeElement.style.backgroundColor = 'yellow'; } } diff --git a/public/docs/_examples/attribute-directives/dart/lib/highlight_directive_2.dart b/public/docs/_examples/attribute-directives/dart/lib/highlight_directive_2.dart index 8c540b3a6a..8546f36279 100644 --- a/public/docs/_examples/attribute-directives/dart/lib/highlight_directive_2.dart +++ b/public/docs/_examples/attribute-directives/dart/lib/highlight_directive_2.dart @@ -1,32 +1,28 @@ // #docregion import 'package:angular2/core.dart'; -@Directive(selector: '[my-highlight]', -// #docregion host +@Directive(selector: '[myHighlight]', + // #docregion host host: const { '(mouseenter)': 'onMouseEnter()', '(mouseleave)': 'onMouseLeave()' } -// #enddocregion host - ) -class Highlight { - final ElementRef _element; -// #docregion mouse-methods - onMouseEnter() { - _highlight("yellow"); - } + // #enddocregion host +) +class HighlightDirective { + // #docregion ctor + final dynamic _el; - onMouseLeave() { - _highlight(null); + HighlightDirective(ElementRef elRef) : _el = elRef.nativeElement; + // #enddocregion ctor + + // #docregion mouse-methods + void onMouseEnter() { _highlight("yellow"); } + void onMouseLeave() { _highlight(); } + + void _highlight([String color]) { + if (_el != null) _el.style.backgroundColor = color; } // #enddocregion mouse-methods - - void _highlight(String color) { - _element.nativeElement.style.backgroundColor = color; - } - -// #docregion ctor - Highlight(this._element); -// #enddocregion ctor } // #enddocregion diff --git a/public/docs/_examples/attribute-directives/ts/app/app.component.1.html b/public/docs/_examples/attribute-directives/ts/app/app.component.1.html index 177c90f5da..7843d3cdf2 100644 --- a/public/docs/_examples/attribute-directives/ts/app/app.component.1.html +++ b/public/docs/_examples/attribute-directives/ts/app/app.component.1.html @@ -1,4 +1,4 @@

My First Attribute Directive

-Highlight me! - \ No newline at end of file +

Highlight me!

+ diff --git a/public/docs/_examples/attribute-directives/ts/app/app.component.html b/public/docs/_examples/attribute-directives/ts/app/app.component.html index 35b5d43aae..e4e445b1a8 100644 --- a/public/docs/_examples/attribute-directives/ts/app/app.component.html +++ b/public/docs/_examples/attribute-directives/ts/app/app.component.html @@ -7,10 +7,9 @@ Yellow Cyan - - +

Highlight me!

- + @@ -18,5 +17,4 @@ Highlight me too!

- - \ No newline at end of file + diff --git a/public/docs/_examples/attribute-directives/ts/app/highlight.directive.1.ts b/public/docs/_examples/attribute-directives/ts/app/highlight.directive.1.ts index afaf652026..f8c1a95ea1 100644 --- a/public/docs/_examples/attribute-directives/ts/app/highlight.directive.1.ts +++ b/public/docs/_examples/attribute-directives/ts/app/highlight.directive.1.ts @@ -1,13 +1,9 @@ // #docregion import { Directive, ElementRef, Input } from '@angular/core'; -@Directive({ - selector: '[myHighlight]' -}) - +@Directive({ selector: '[myHighlight]' }) export class HighlightDirective { constructor(el: ElementRef) { el.nativeElement.style.backgroundColor = 'yellow'; } } -// #enddocregion \ No newline at end of file diff --git a/public/docs/_examples/attribute-directives/ts/app/highlight.directive.ts b/public/docs/_examples/attribute-directives/ts/app/highlight.directive.ts index 95b79c42ce..6ec9842602 100644 --- a/public/docs/_examples/attribute-directives/ts/app/highlight.directive.ts +++ b/public/docs/_examples/attribute-directives/ts/app/highlight.directive.ts @@ -9,39 +9,28 @@ import { Directive, ElementRef, Input } from '@angular/core'; '(mouseleave)': 'onMouseLeave()' } }) - // #docregion class-1 export class HighlightDirective { - private _defaultColor = 'red'; - private el:HTMLElement; -// #enddocregion class-1 -// #enddocregion full - /* -// #docregion highlight - @Input() myHighlight: string; -// #enddocregion highlight - */ -// #docregion full + private el: HTMLElement; + + constructor(el: ElementRef) { this.el = el.nativeElement; } + // #enddocregion class-1 -// #docregion defaultColor + // #docregion defaultColor @Input() set defaultColor(colorName:string){ this._defaultColor = colorName || this._defaultColor; } -// #enddocregion defaultColor -// #docregion class-1 + // #enddocregion defaultColor + // #docregion class-1 -// #docregion color + // #docregion color @Input('myHighlight') highlightColor: string; -// #enddocregion color + // #enddocregion color -// #enddocregion class-1 -// #docregion class-1 - constructor(el: ElementRef) { this.el = el.nativeElement; } - -// #docregion mouse-enter + // #docregion mouse-enter onMouseEnter() { this.highlight(this.highlightColor || this._defaultColor); } -// #enddocregion mouse-enter + // #enddocregion mouse-enter onMouseLeave() { this.highlight(null); } private highlight(color:string) { @@ -50,3 +39,8 @@ export class HighlightDirective { } // #enddocregion class-1 // #enddocregion full +/* +// #docregion highlight +@Input() myHighlight: string; +// #enddocregion highlight +*/ diff --git a/public/docs/_examples/attribute-directives/ts/index.html b/public/docs/_examples/attribute-directives/ts/index.html index 6bfef2480d..99b6749fbd 100644 --- a/public/docs/_examples/attribute-directives/ts/index.html +++ b/public/docs/_examples/attribute-directives/ts/index.html @@ -19,10 +19,7 @@ System.import('app').catch(function(err){ console.error(err); }); - - loading... - diff --git a/public/docs/dart/latest/_util-fns.jade b/public/docs/dart/latest/_util-fns.jade index e326dc5323..8a76147a0d 100644 --- a/public/docs/dart/latest/_util-fns.jade +++ b/public/docs/dart/latest/_util-fns.jade @@ -1,18 +1,17 @@ include ../../../_includes/_util-fns +//- See the _util-fns file included above for a description of the use of these variables. - var _docsFor = 'dart'; - -mixin privateVar(varName) - | _#{varName} +- var _decorator = 'annotation'; +- var _priv = '_'; mixin liveExampleLink(linkText, exampleUrlPartName) a(href='https://angular-examples.github.io/#{exampleUrlPartName}')= linkText mixin liveExampleLink2(linkText, exampleUrlPartName) - var liveExampleSourceLinkText = attributes.srcLinkText || 'view source' - span. - #[+liveExampleLink(linkText, exampleUrlPartName)] - (#[a(href='https://github.com/angular-examples/#{exampleUrlPartName}') #{liveExampleSourceLinkText}]) + | #[+liveExampleLink(linkText, exampleUrlPartName)] + | (#[a(href='https://github.com/angular-examples/#{exampleUrlPartName}') #{liveExampleSourceLinkText}]) //- Deprecated mixin liveExLinks(exampleUrlPartName) @@ -42,8 +41,8 @@ mixin liveExLinks(exampleUrlPartName) - if(!_title || !adjustExamplePath) return _title; - var title = _title.trim(); - // Assume title is a path if it ends with an extension like '.foo', -- // optionally followed by '(excerpt)' with or without parentheses. -- var matches = title.match(/(.*\.\w+)($|\s*\(?excerpt\)?$)/); +- // optionally followed by some comment in parentheses. +- var matches = title.match(/(.*\.\w+)($|\s*\([\w ]+\)?$)/); - if(matches && matches.length == 3) { - // e.g. matches == ['abc.ts (excerpt)', 'abc.ts', ' (excerpt)'] - var path = adjustExamplePath(matches[1]); diff --git a/public/docs/dart/latest/guide/attribute-directives.jade b/public/docs/dart/latest/guide/attribute-directives.jade index 25afd1888d..350cd60b88 100644 --- a/public/docs/dart/latest/guide/attribute-directives.jade +++ b/public/docs/dart/latest/guide/attribute-directives.jade @@ -1,12 +1,9 @@ -include ../_util-fns +extends ../../../ts/latest/guide/attribute-directives.jade -:marked - We're working on the Dart version of this chapter. - In the meantime, please see these resources: - - * [Attribute Directives](/docs/ts/latest/guide/attribute-directives.html): - The TypeScript version of this chapter - - * [Dart source code](https://github.com/angular/angular.io/tree/master/public/docs/_examples/attribute-directives/dart): - A preliminary version of the example code that will appear in this chapter +block includes + include ../_util-fns +block highlight-directive-1 + :marked + We begin by importing the Angular `core`. + Then we define the directive metadata by means of the `@Directive` annotation. diff --git a/public/docs/ts/latest/_util-fns.jade b/public/docs/ts/latest/_util-fns.jade index 182471739b..05c8256082 100644 --- a/public/docs/ts/latest/_util-fns.jade +++ b/public/docs/ts/latest/_util-fns.jade @@ -1,14 +1,13 @@ include ../../../_includes/_util-fns -- var docsFor = 'ts'; - -mixin privateVar(varName) - | #{varName} +//- See the _util-fns file included above for a description of the use of these variables. +- var _docsFor = 'ts'; +- var _decorator = 'decorator'; +- var _priv = ''; mixin liveExampleLink(linkText, exampleUrlPartName) a(href='/resources/live-examples/#{exampleUrlPartName}/ts/plnkr.html')= linkText mixin liveExampleLink2(linkText, exampleUrlPartName) //- In Dart this also gives a link to the source. - span. - #[+liveExampleLink(linkText, exampleUrlPartName)] + | #[+liveExampleLink(linkText, exampleUrlPartName)] diff --git a/public/docs/ts/latest/guide/attribute-directives.jade b/public/docs/ts/latest/guide/attribute-directives.jade index 3c285c4497..7b43bbe9e8 100644 --- a/public/docs/ts/latest/guide/attribute-directives.jade +++ b/public/docs/ts/latest/guide/attribute-directives.jade @@ -1,17 +1,18 @@ -include ../_util-fns +block includes + include ../_util-fns :marked An **Attribute** directive changes the appearance or behavior of a DOM element. :marked In this chapter we will - * write an attribute directive to change the background color - * apply the attribute directive to an element in a template - * respond to user-initiated events - * pass values into the directive using data binding - - [Live Example](/resources/live-examples/attribute-directives/ts/plnkr.html) - + * [write an attribute directive to change the background color](#write-directive) + * [apply the attribute directive to an element in a template](#apply-directive) + * [respond to user-initiated events](#respond-to-user) + * [pass values into the directive using data binding](#bindings) +p. + #[+liveExampleLink2('Live example', 'attribute-directives')]. +:marked ## Directives overview There are three kinds of directives in Angular: @@ -19,14 +20,14 @@ include ../_util-fns 1. Structural directives 1. Attribute directives - The *Component* is really a directive with a template. - It's the most common of the three directives and we write lots of them as we build our application. + A *Component* is really a directive with a template. + It's the most common of the three directives and we tend to write lots of them as we build applications. - The [*Structural* directive](structural-directives.html) changes the DOM layout by adding and removing DOM elements. - [NgFor](template-syntax.html#ng-for) and [NgIf](template-syntax.html#ng-if) are two familiar examples. + [*Structural* directives](structural-directives.html) can change the DOM layout by adding and removing DOM elements. + [NgFor](template-syntax.html#ngFor) and [NgIf](template-syntax.html#ngIf) are two familiar examples. - The *Attribute* directive changes the appearance or behavior of an element. - The built-in [NgStyle](template-syntax.html#ng-style) directive, for example, + An *Attribute* directive can change the appearance or behavior of an element. + The built-in [NgStyle](template-syntax.html#ngStyle) directive, for example, can change several element styles at the same time. We are going to write our own attribute directive to set an element's background color @@ -35,9 +36,9 @@ include ../_util-fns :marked We don't need *any* directive to simply set the background color. We can set it with the special [Style Binding](template-syntax.html#style-binding) like this: - code-example. - <p [style.background]="'lime'">I am green with envy!</p> -
+ code-example(language="html" escapse="html"). +

I am green with envy!

+ :marked That wouldn't be nearly as much fun as creating our own directive. @@ -45,10 +46,11 @@ include ../_util-fns in response to a user action, a mouse hover. .l-main-section +a#write-directive :marked ## Build a simple attribute directive - An attribute directive minimally requires building a controller class annotated with a - `Directive` decorator. The `Directive` decorator specifies the selector identifying + An attribute directive minimally requires building a controller class annotated with + `@Directive`, which specifies the selector identifying the attribute associated with the directive. The controller class implements the desired directive behavior. @@ -60,23 +62,24 @@ include ../_util-fns include ../_quickstart_repo :marked - Add a new file to the `app` folder called `highlight.directive.ts` and add the following code: + Create the following source file in the indicated folder with the given code: +makeExample('attribute-directives/ts/app/highlight.directive.1.ts', null, 'app/highlight.directive.ts') +block highlight-directive-1 + :marked + We begin by importing some symbols from the Angular `core`. + We need the `Directive` symbol for the `@Directive` decorator. + We need the `ElementRef` to [inject](dependency-injection.html) into the directive's constructor + so we can access the DOM element. + We don't need `Input` immediately but we will need it later in the chapter. + + Then we define the directive metadata in a configuration object passed + as an argument to the `@Directive` decorator function. :marked - We begin by importing some symbols from the Angular library. - We need the `Directive` symbol for the `@Directive` decorator. - We need the `ElementRef` to [inject](dependency-injection.html) into the directive's constructor - so we can access the DOM element. - We don't need `Input` immediately but we will need it later in the chapter. - - Then we define the directive metadata in a configuration object passed - as an argument to the `@Directive` decorator function. - A `@Directive` decorator for an attribute directive requires a css selector to identify + `@Directive` requires a CSS selector to identify the HTML in the template that is associated with our directive. - The [css selector for an attribute](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) + The [CSS selector for an attribute](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) is the attribute name in square brackets. - Our directive's selector is `[myHighlight]`. Angular will locate all elements in the template that have an attribute named `myHighlight`. .l-sub-section @@ -89,33 +92,33 @@ include ../_quickstart_repo There is also less risk of colliding with a third-party directive name when we give ours a prefix. We do **not** prefix our `highlight` directive name with **`ng`**. - That prefix belongs to Angular and - we don't want to confuse our directives with their directives. + That prefix belongs to Angular. We need a prefix of our own, preferably short, and `my` will do for now. - +p + | After the `@Directive` metadata comes the directive's controller class, which contains the logic for the directive. + +ifDocsFor('ts') + | We export `HighlightDirective` to make it accessible to other components. :marked - After the `@Directive` metadata comes the directive's controller class which we are exporting - to make it accessible to other components. - The directive's controller class contains the logic for the directive. - Angular creates a new instance of the directive's controller class for each matching element, injecting an Angular `ElementRef` into the constructor. - `ElementRef` is a service that grants us direct access to the DOM element through its `nativeElement` property. That's all we need to set the element's background color using the browser DOM API. .l-main-section +a#apply-directive :marked ## Apply the attribute directive The `AppComponent` in this sample is a test harness for our `HighlightDirective`. Let's give it a new template that - applies the directive as an attribute to a `span` element. - In Angular terms, the `` element will be the attribute **host**. - - We'll put the template in its own `app.component.html` file that looks like this: + applies the directive as an attribute to a paragraph (`p`) element. + In Angular terms, the `

` element will be the attribute **host**. +p + | We'll put the template in its own + code #[+adjExPath('app.component.html')] + | file that looks like this: +makeExample('attribute-directives/ts/app/app.component.1.html',null,'app/app.component.html')(format=".") :marked A separate template file is clearly overkill for a 2-line template. @@ -123,59 +126,60 @@ include ../_quickstart_repo Meanwhile, we'll revise the `AppComponent` to reference this template. +makeExample('attribute-directives/ts/app/app.component.ts',null,'app/app.component.ts') :marked - We've added an `import` statement to fetch the 'Highlight' directive and - added that class to a `directives` array in the component metadata so that Angular + We've added an `import` statement to fetch the 'Highlight' directive and, + added that class to a `directives` component metadata so that Angular will recognize our directive when it encounters `myHighlight` in the template. - We run the app and see that our directive highlights the span text. + We run the app and see that our directive highlights the paragraph text. figure.image-display img(src="/resources/images/devguide/attribute-directives/first-highlight.png" alt="First Highlight") .l-sub-section :marked - #### Why isn't my directive working? + ### Your directive isn't working? - Did you remember to set the `directives` array? It is easy to forget! + Did you remember to set the `directives` attribute of `@Component`? It is easy to forget! Open the console in the browser tools and look for an error like this: - code-example.format(""). + code-example(format="nocode"). EXCEPTION: Template parse errors: - Can't bind to 'myHighlight' since it isn't a known native property + Can't bind to 'myHighlight' since it isn't a known native property :marked Angular detects that we're trying to bind to *something* but it doesn't know what. We have to tell it by listing `HighlightDirective` in the `directives` metadata array. :marked Let's recap what happened. - Angular found the `myHighlight` attribute on the `` element. It created + Angular found the `myHighlight` attribute on the `

` element. It created an instance of the `HighlightDirective` class, injecting a reference to the element into the constructor - where we set the `` element's background style to yellow. + where we set the `

` element's background style to yellow. .l-main-section +a#respond-to-user :marked ## Respond to user action We are not satisfied to simply set an element color. Our directive should set the color in response to a user action. - Specifically, we want to set the color when the user mouses over the element. + Specifically, we want to set the color when the user hovers over an element. We'll need to - 1. detect when the user mouses into and out of the element - 1. respond to those actions by setting and clearing the highlight color. + 1. detect when the user hovers into and out of the element, + 1. respond to those actions by setting and clearing the highlight color, respectively. - Start with event detection. - We add a `host` property to the directive metadata and give it a configuration object - that specifies two mouse events and the directive methods to call when they are raised. + Let's start with event detection. + Add a `host` property to the directive metadata and give it a configuration object + that specifies two mouse events and the directive methods to call when they are raised: + +makeExample('attribute-directives/ts/app/highlight.directive.2.ts','host')(format=".") -:marked + .l-sub-section :marked - The `host` property refers to the DOM element that hosts our attribute directive, the `` in our case. + The `host` property refers to the DOM element that hosts our attribute directive, the `

` in our case. - We could have attached an event listener to the native element (`el.nativeElement`) with - plain old JavaScript. - There are at least three problems with that approach: + We could have attached event listeners by manipulating the host DOM element directly, but + there are at least three problems with such an approach: 1. We have to write the listeners correctly. 1. We must *detach* our listener when the directive is destroyed to avoid memory leaks. @@ -183,65 +187,63 @@ figure.image-display Let's roll with the `host` property. :marked - Now we implement those two mouse event handlers: + Now we implement the two mouse event handlers: +makeExample('attribute-directives/ts/app/highlight.directive.2.ts','mouse-methods')(format=".") :marked - Notice that they delegate to a helper method that sets the color via a private local variable, `el`. - We revise the constructor to capture the `ElementRef.nativeElement` in `el`. + Notice that they delegate to a helper method that sets the color via a private local variable, `#{_priv}el`. + We revise the constructor to capture the `ElementRef.nativeElement` in this variable. +makeExample('attribute-directives/ts/app/highlight.directive.2.ts','ctor')(format=".") :marked Here's the updated directive: +makeExample('attribute-directives/ts/app/highlight.directive.2.ts',null, 'app/highlight.directive.ts') :marked - We run the app and confirm that the background color appears as we move the mouse over the `span` and + We run the app and confirm that the background color appears as we move the mouse over the `p` and disappears as we move out. figure.image-display img(src="/resources/images/devguide/attribute-directives/highlight-directive-anim.gif" alt="Second Highlight") -:marked .l-main-section +a#bindings :marked ## Configure the directive with binding - + Currently the highlight color is hard-coded within the directive. That's inflexible. - We should set the highlight color externally with a binding like this: -+makeExample('attribute-directives/ts/app/app.component.html','span') + We should set the color externally with a binding like this: ++makeExample('attribute-directives/ts/app/app.component.html','pHost') :marked We'll extend our directive class with a bindable **input** `highlightColor` property and use it when we highlight text. Here is the final version of the class: - +makeExample('attribute-directives/ts/app/highlight.directive.ts', 'class-1', 'app/highlight.directive.ts (class only)') - +a#input :marked - The new `highlightColor` property is called an "input" property because data flows from the binding expression into our directive. - Notice that we call the `@Input()` decorator function while defining the property. + The new `highlightColor` property is called an *input* property because data flows from the binding expression into our directive. + Notice the `@Input()` #{_decorator} applied to the property. +makeExample('attribute-directives/ts/app/highlight.directive.ts', 'color') :marked - This `@Input` decorator adds metadata to the class that makes the `highlightColor` property available for property binding - under the `myHighlight` alias. + `@Input` adds metadata to the class that makes the `highlightColor` property available for + property binding under the `myHighlight` alias. We must add this input metadata or Angular will reject the binding. See the [appendix](#why-input) below to learn why. .l-sub-section :marked - ### @Input(alias) - The developer who uses our directive expects to bind to the attribute name, `myHighlight`. + ### @Input(_alias_) + The developer who uses this directive expects to bind to the attribute name, `myHighlight`. The directive property name is `highlightColor`. That's a disconnect. - We can resolve the discrepancy by renaming the property to `myHighlight` and define it as follows: + We could resolve the discrepancy by renaming the property to `myHighlight` and define it as follows: +makeExample('attribute-directives/ts/app/highlight.directive.ts', 'highlight') -
:marked Maybe we don't want that property name inside the directive perhaps because it doesn't express our intention well. We can **alias** the `highlightColor` property with the attribute name by - passing `myHighlight` into the `@Input` decorator: + passing `myHighlight` into the `@Input` #{_decorator}: +makeExample('attribute-directives/ts/app/highlight.directive.ts', 'color') :marked Now that we're getting the highlight color as an input, we modify the `onMouseEnter()` method to use it instead of the hard-coded color name. - We also define a red default color as a fallback in case + We also define red as the default color to fallback on in case the user neglects to bind with a color. +makeExample('attribute-directives/ts/app/highlight.directive.ts', 'mouse-enter') :marked @@ -249,7 +251,6 @@ figure.image-display users pick the highlight color and bind their choice to our directive. Here is the updated template: - +makeExample('attribute-directives/ts/app/app.component.html', 'v2') .l-sub-section @@ -279,7 +280,7 @@ figure.image-display ## Bind to a second property Our directive only has a single, customizable property. What if we had ***two properties***? - Let's let the template developer set the default color, the color that prevails until the user picks a highlight color. + Let's allow the template developer to set the default color, the color that prevails until the user picks a highlight color. We'll add a second **input** property to `HighlightDirective` called `defaultColor`: +makeExample('attribute-directives/ts/app/highlight.directive.ts', 'defaultColor')(format=".") :marked @@ -307,11 +308,11 @@ figure.image-display .l-main-section :marked ## Summary - Now we know how to - - build a simple **attribute directive** to attach behavior to an HTML element, - - use that directive in a template, - - respond to **events** to change behavior based on an event, - - and use **binding** to pass values to the attribute directive. + We now know how to + - [build a simple **attribute directive** to attach behavior to an HTML element](#write-directive), + - [use that directive in a template](#apply-directive), + - [respond to **events** to change behavior based on an event](#respond-to-user), + - and [use **binding** to pass values to the attribute directive](#bindings). The final source: @@ -331,7 +332,7 @@ figure.image-display `) - +a#why-input .l-main-section :marked ### Appendix: Input properties @@ -349,7 +350,7 @@ figure.image-display A property is a *target* when it appears in **square brackets** ([ ]) to the **left** of the equals (=) ... as it is does when we bind to the `myHighlight` property of the `HighlightDirective`, -+makeExample('attribute-directives/ts/app/app.component.html','span')(format=".") ++makeExample('attribute-directives/ts/app/app.component.html','pHost')(format=".") :marked The 'color' in `[myHighlight]="color"` is a binding ***source***. A source property doesn't require a declaration. diff --git a/public/docs/ts/latest/guide/structural-directives.jade b/public/docs/ts/latest/guide/structural-directives.jade index d58afd20a8..d3597284ab 100644 --- a/public/docs/ts/latest/guide/structural-directives.jade +++ b/public/docs/ts/latest/guide/structural-directives.jade @@ -125,7 +125,7 @@ figure.image-display `structural-directives/ts/app/structural-directives.component.html, structural-directives/ts/app/heavy-loader.component.ts`, 'message-log,', - 'template excerpt, heavy-loader.component.ts') + 'template (excerpt), heavy-loader.component.ts') :marked We also log when a component is created or destroyed