From 6e11cf6a1e62eba063a5b67df1386d733d6ef940 Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Tue, 26 Jan 2016 13:42:17 -0800 Subject: [PATCH] docs(attribute directives/TS/Dart): remove `Renderer`; improve text closes #757 --- .../dart/lib/highlight_directive.dart | 5 +- .../dart/lib/highlight_directive_1.dart | 5 +- .../dart/lib/highlight_directive_2.dart | 5 +- .../ts/app/highlight.directive.1.ts | 7 +- .../ts/app/highlight.directive.2.ts | 7 +- .../ts/app/highlight.directive.ts | 6 +- .../ts/app/{boot.ts => main.ts} | 0 .../attribute-directives/ts/index.html | 6 +- .../ts/latest/guide/attribute-directives.jade | 81 ++++++++----------- 9 files changed, 52 insertions(+), 70 deletions(-) rename public/docs/_examples/attribute-directives/ts/app/{boot.ts => main.ts} (100%) 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 4dfe4b519e..8367ac6eb2 100644 --- a/public/docs/_examples/attribute-directives/dart/lib/highlight_directive.dart +++ b/public/docs/_examples/attribute-directives/dart/lib/highlight_directive.dart @@ -32,7 +32,6 @@ class Highlight { // #enddocregion defaultColor // #docregion class-1 - final Renderer _renderer; final ElementRef _element; // #docregion mouse-enter @@ -46,10 +45,10 @@ class Highlight { } void _highlight(String color) { - _renderer.setElementStyle(_element, 'background-color', color); + _element.nativeElement.style.backgroundColor = color; } - Highlight(this._element, this._renderer); + Highlight(this._element); } // #enddocregion class-1 // #enddocregion full 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 468f2b991b..4fef486203 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 @@ -5,8 +5,7 @@ import 'package:angular2/angular2.dart'; @Directive(selector: '[my-highlight]') class Highlight { - Highlight(ElementRef element, Renderer renderer) { - //el.nativeElement.style.backgroundColor = 'yellow'; - renderer.setElementStyle(element, 'background-color', 'yellow'); + Highlight(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 00d92491ea..f0701bf506 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 @@ -12,7 +12,6 @@ import 'package:angular2/angular2.dart'; // #enddocregion host ) class Highlight { - final Renderer _renderer; final ElementRef _element; // #docregion mouse-methods onMouseEnter() { @@ -25,11 +24,11 @@ class Highlight { // #enddocregion mouse-methods void _highlight(String color) { - _renderer.setElementStyle(_element, 'background-color', color); + _element.nativeElement.style.backgroundColor = color; } // #docregion ctor - Highlight(this._element, this._renderer); + Highlight(this._element); // #enddocregion ctor } // #enddocregion 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 bb7cba13e7..9b4dbd7448 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,14 +1,13 @@ // #docregion -import {Directive, ElementRef, Renderer, Input} from 'angular2/core'; +import {Directive, ElementRef, Input} from 'angular2/core'; @Directive({ selector: '[myHighlight]' }) export class HighlightDirective { - constructor(el: ElementRef, renderer: Renderer) { - //el.nativeElement.style.backgroundColor = 'yellow'; - renderer.setElementStyle(el, 'backgroundColor', 'yellow'); + 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.2.ts b/public/docs/_examples/attribute-directives/ts/app/highlight.directive.2.ts index c14bc66e55..9cf0b95970 100644 --- a/public/docs/_examples/attribute-directives/ts/app/highlight.directive.2.ts +++ b/public/docs/_examples/attribute-directives/ts/app/highlight.directive.2.ts @@ -1,5 +1,5 @@ // #docregion -import {Directive, ElementRef, Renderer, Input} from 'angular2/core'; +import {Directive, ElementRef, Input} from 'angular2/core'; @Directive({ selector: '[myHighlight]', @@ -13,8 +13,7 @@ import {Directive, ElementRef, Renderer, Input} from 'angular2/core'; export class HighlightDirective { // #docregion ctor - constructor(private el: ElementRef, private renderer: Renderer) { - } + constructor(private el: ElementRef) { } // #enddocregion ctor // #docregion mouse-methods @@ -22,7 +21,7 @@ export class HighlightDirective { onMouseLeave() { this._highlight(null); } private _highlight(color: string) { - this.renderer.setElementStyle(this.el, 'backgroundColor', color); + this.el.nativeElement.style.backgroundColor = color; } // #enddocregion mouse-methods 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 7cce1a3c8e..6a26780057 100644 --- a/public/docs/_examples/attribute-directives/ts/app/highlight.directive.ts +++ b/public/docs/_examples/attribute-directives/ts/app/highlight.directive.ts @@ -1,6 +1,6 @@ // #docplaster // #docregion full -import {Directive, ElementRef, Renderer, Input} from 'angular2/core'; +import {Directive, ElementRef, Input} from 'angular2/core'; @Directive({ selector: '[myHighlight]', @@ -34,7 +34,7 @@ export class HighlightDirective { // #enddocregion defaultColor // #docregion class-1 - constructor(private el: ElementRef, private renderer: Renderer) { } + constructor(private el: ElementRef) { } // #docregion mouse-enter onMouseEnter() { this._highlight(this.highlightColor || this._defaultColor); } @@ -42,7 +42,7 @@ export class HighlightDirective { onMouseLeave() { this._highlight(null); } private _highlight(color:string) { - this.renderer.setElementStyle(this.el, 'backgroundColor', color); + this.el.nativeElement.style.backgroundColor = color; } } // #enddocregion class-1 diff --git a/public/docs/_examples/attribute-directives/ts/app/boot.ts b/public/docs/_examples/attribute-directives/ts/app/main.ts similarity index 100% rename from public/docs/_examples/attribute-directives/ts/app/boot.ts rename to public/docs/_examples/attribute-directives/ts/app/main.ts diff --git a/public/docs/_examples/attribute-directives/ts/index.html b/public/docs/_examples/attribute-directives/ts/index.html index ab1f9adcb4..985253770a 100644 --- a/public/docs/_examples/attribute-directives/ts/index.html +++ b/public/docs/_examples/attribute-directives/ts/index.html @@ -7,21 +7,21 @@ - + diff --git a/public/docs/ts/latest/guide/attribute-directives.jade b/public/docs/ts/latest/guide/attribute-directives.jade index 0014a74125..1438c30c6d 100644 --- a/public/docs/ts/latest/guide/attribute-directives.jade +++ b/public/docs/ts/latest/guide/attribute-directives.jade @@ -64,9 +64,9 @@ include ../../../../_includes/_util-fns :marked We begin by importing some symbols from the Angular library. We need the `Directive` symbol for the `@Directive` decorator. - We need symbols for the *Element Reference* and the *Renderer* service that - we will [inject](dependency-injection.html) into the directive's constructor. - We don't need `Input` now but we will need it later in the chapter. + 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. @@ -98,40 +98,17 @@ include ../../../../_includes/_util-fns 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 *Element Reference* and - the *Renderer* service as arguments to the constructor. - We'll need those *services* to set the element's background color. - - Our code shows two ways to set the color. + each matching element, injecting an Angular `ElementRef` + into the constructor. - We could access the `nativeElement` property of the element reference - and set the element's background color using the browser DOM API. We don't need - the `Renderer` for this approach. - - We commented this technique out. It works. But we don't like it. + `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. - We prefer the second way that relies on the `Renderer` service - to set the element properties. - -.l-sub-section - :marked - ### Why prefer the Renderer? - Manipulating the DOM directly is a practice we'd rather *avoid* because it chains us - to the browser DOM API. - - The `Renderer` insulates our code from the browser's API. - That gives us options. - The rendering phase could be offloaded to a Web Worker for faster performance. - Our directive might work when we ran the application outside the browser, - perhaps on the server in a pre-render phase. - Server-side rendering can make our application load faster and - is often friendlier to Search Engine Optimizations (SEO). - -:marked .l-main-section :marked ## Apply the attribute directive - The `AppComponent` will be the test harness for our `HighlightDirective`. + 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**. @@ -147,19 +124,31 @@ include ../../../../_includes/_util-fns 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 will recognize our directive when it encounters `myHighlight` in the template. - Angular would simply ignore the `myHighlight` attribute without it. - + We run the app and see that our directive highlights the span 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? + + Did you remember to set the `directives` array? It is easy to forget! + + Open the console in the browser tools and look for an error like this: + code-example.format(""). + EXCEPTION: Template parse errors: + 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 an instance of the `HighlightDirective` class, - injecting both a reference to the element and the `Renderer` service into the constructor. - The constructor told the `Renderer` to set the `` element's background style to yellow. + injecting a reference to the element into the constructor + where we set the `` element's background style to yellow. .l-main-section :marked @@ -195,12 +184,11 @@ figure.image-display Now we implement those 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 calls the `Renderer` service - as we used to do in the constructor. + Notice that they delegate to a helper method to set the color. We no longer need the constructor body but - we still want the injected `ElementRef` and `Renderer` service. - We revise the constructor signature to capture the injectables in private variables + we still want the injected `ElementRef`. + We revise the constructor signature to capture the injected `ElementRef` in a private variable and clear the body. +makeExample('attribute-directives/ts/app/highlight.directive.2.ts','ctor')(format=".") :marked @@ -233,12 +221,11 @@ figure.image-display :marked This `@Input` decorator adds metadata to the class that makes the `highlightColor` property available for property binding under the `myHighlight` alias. - We must add this input metadata. - Angular will reject a binding to this property if we don't declare it as an input. - + 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`. The directive property name is `highlightColor`. That's a disconnect. @@ -333,14 +320,14 @@ figure.image-display `attribute-directives/ts/app/app.component.ts, attribute-directives/ts/app/app.component.html, attribute-directives/ts/app/highlight.directive.ts, - attribute-directives/ts/app/boot.ts, + attribute-directives/ts/app/main.ts, attribute-directives/ts/index.html `, ',,full', `app.component.ts, app.component.html, highlight.directive.ts, - boot.ts, + main.ts, index.html `) @@ -359,9 +346,9 @@ figure.image-display Angular makes a subtle but important distinction between binding **sources** and **targets**. In all previous bindings, the directive or component property was a binding ***source***. - A property is a *source* if it appears in the template expression to the ***right*** of the (=). + A property is a *source* if it appears in the template expression to the ***right*** of the equals (=). - A property is a *target* when it appears to the **left** of the (=) ... + 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=".") :marked