docs(dev guide): attribute-directives - updated dart/ts code and new dart prose

Mainly copyedits and prep for extension

+ example code cleanup & bug fix
+ fix bug in default color initialization
This commit is contained in:
Patrice Chalin 2016-05-06 07:42:01 -07:00 committed by Thibault Sottiaux
parent ac92e77611
commit e958be24bf
17 changed files with 201 additions and 216 deletions

View File

@ -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)}

View File

@ -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;
}

View File

@ -7,14 +7,14 @@
<input type="radio" name="colors" (click)="color='yellow'">Yellow
<input type="radio" name="colors" (click)="color='cyan'">Cyan
</div>
<!-- #docregion span -->
<p><span [my-highlight]="color">Highlight me!</span></p>
<!-- #enddocregion span -->
<!-- #docregion pHost -->
<p [myHighlight]="color">Highlight me!</p>
<!-- #enddocregion pHost -->
<!-- #enddocregion v2 -->
<!-- #docregion defaultColor -->
<p><span [my-highlight]="color" [default-color]="'violet'">
<p [myHighlight]="color" [defaultColor]="'violet'">
Highlight me too!
</span></p>
</p>
<!-- #enddocregion defaultColor -->
<!-- #enddocregion -->

View File

@ -1,3 +1,3 @@
<!-- #docregion -->
<h1>My First Attribute Directive</h1>
<span my-highlight>Highlight me!</span>
<p myHighlight>Highlight me!</p>

View File

@ -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
onMouseEnter() {
_highlight(highlightColor ?? _defaultColor);
// #docregion mouse-enter
void onMouseEnter() { _highlight(highlightColor ?? _defaultColor); }
// #enddocregion mouse-enter
void onMouseLeave() { _highlight(); }
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
*/

View File

@ -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';
}
}

View File

@ -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

View File

@ -1,4 +1,4 @@
<!-- #docregion -->
<h1>My First Attribute Directive</h1>
<span myHighlight>Highlight me!</span>
<p myHighlight>Highlight me!</p>
<!-- #enddocregion -->

View File

@ -7,10 +7,9 @@
<input type="radio" name="colors" (click)="color='yellow'">Yellow
<input type="radio" name="colors" (click)="color='cyan'">Cyan
</div>
<!-- #docregion span -->
<!-- #docregion pHost -->
<p [myHighlight]="color">Highlight me!</p>
<!-- #enddocregion span -->
<!-- #enddocregion pHost -->
<!-- #enddocregion v2 -->
<!-- #docregion defaultColor -->
@ -18,5 +17,4 @@
Highlight me too!
</p>
<!-- #enddocregion defaultColor -->
<!-- #enddocregion -->

View File

@ -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

View File

@ -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;
// #docregion defaultColor
constructor(el: ElementRef) { this.el = el.nativeElement; }
// #enddocregion class-1
// #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
*/

View File

@ -19,10 +19,7 @@
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<my-app>loading...</my-app>
</body>
</html>

View File

@ -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]);

View File

@ -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.

View File

@ -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)]

View File

@ -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.
&lt;p [style.background]="'lime'">I am green with envy!&lt;/p>
<br>
code-example(language="html" escapse="html").
<p [style.background]="'lime'">I am green with envy!</p>
: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,11 +62,12 @@ 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')
:marked
We begin by importing some symbols from the Angular library.
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.
@ -72,11 +75,11 @@ include ../_quickstart_repo
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
:marked
`@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 `<span>` 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 `<p>` 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,22 +126,22 @@ 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
:marked
@ -147,35 +150,36 @@ figure.image-display
:marked
Let's recap what happened.
Angular found the `myHighlight` attribute on the `<span>` element. It created
Angular found the `myHighlight` attribute on the `<p>` element. It created
an instance of the `HighlightDirective` class,
injecting a reference to the element into the constructor
where we set the `<span>` element's background style to yellow.
where we set the `<p>` 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.
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:
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.
+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 `<span>` in our case.
The `host` property refers to the DOM element that hosts our attribute directive, the `<p>` 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 id="input"></a>
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')
<br>
: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 id="why-input"></a>
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.

View File

@ -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