docs: edit attribute-directives.md, move best practice to styleguide (#39849)

PR Close #39849
This commit is contained in:
Kapunahele Wong 2020-11-24 08:49:34 -05:00 committed by Andrew Scott
parent 542ba1fc00
commit 30d5e25a28
6 changed files with 102 additions and 342 deletions

View File

@ -4,11 +4,7 @@
<p appHighlight>Highlight me!</p>
<!-- #enddocregion applied -->
<!-- #docregion color-1 -->
<p appHighlight highlightColor="yellow">Highlighted in yellow</p>
<p appHighlight [highlightColor]="'orange'">Highlighted in orange</p>
<!-- #enddocregion color-1 -->
<!-- #docregion color-2 -->
<p appHighlight [highlightColor]="color">Highlighted with parent component's color</p>
<!-- #enddocregion color-2 -->

View File

@ -1,8 +1,8 @@
/* tslint:disable:no-unused-variable member-ordering */
// #docplaster
// #docregion imports,
// #docregion imports
import { Directive, ElementRef, HostListener } from '@angular/core';
// #enddocregion imports,
// #enddocregion imports
import { Input } from '@angular/core';
// #docregion
@ -10,9 +10,8 @@ import { Input } from '@angular/core';
selector: '[appHighlight]'
})
export class HighlightDirective {
// #docregion ctor
constructor(private el: ElementRef) { }
// #enddocregion ctor
// #docregion mouse-methods
@HostListener('mouseenter') onMouseEnter() {
@ -26,16 +25,10 @@ export class HighlightDirective {
private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
// #enddocregion mouse-methods,
// #docregion color
@Input() highlightColor: string;
// #enddocregion color
// #enddocregion mouse-methods
// #docregion color-2
@Input() appHighlight: string;
// #enddocregion color-2
// #docregion
}
// #enddocregion

View File

@ -12,11 +12,9 @@ export class HighlightDirective {
@Input('appHighlight') highlightColor: string;
// #docregion mouse-enter
@HostListener('mouseenter') onMouseEnter() {
this.highlight(this.highlightColor || 'red');
}
// #enddocregion mouse-enter
@HostListener('mouseleave') onMouseLeave() {
this.highlight(null);

View File

@ -12,9 +12,7 @@ export class HighlightDirective {
@Input() defaultColor: string;
// #enddocregion defaultColor
// #docregion color
@Input('appHighlight') highlightColor: string;
// #enddocregion color
// #docregion mouse-enter
@HostListener('mouseenter') onMouseEnter() {

View File

@ -1,408 +1,174 @@
# Attribute directives
An **Attribute** directive changes the appearance or behavior of a DOM element.
With attribute directives, you can change the appearance or behavior of DOM elements and Angular components.
Try the <live-example title="Attribute Directive example"></live-example>.
<div class="alert is-helpful">
{@a directive-overview}
See the <live-example></live-example> for a working example containing the code snippets in this guide.
## Directives overview
</div>
There are three kinds of directives in Angular:
## Building an attribute directive
1. Components&mdash;directives with a template.
1. Structural directives&mdash;change the DOM layout by adding and removing DOM elements.
1. Attribute directives&mdash;change the appearance or behavior of an element, component, or another directive.
This section walks you through creating a highlight directive that sets the background color of the host element to yellow.
*Components* are the most common of the three directives.
You saw a component for the first time in the [Getting Started](start "Getting Started with Angular") tutorial.
1. To create a directive, use the CLI command [`ng generate directive`](cli/generate).
*Structural Directives* change the structure of the view.
Two examples are [NgFor](guide/built-in-directives#ngFor) and [NgIf](guide/built-in-directives#ngIf).
Learn about them in the [Structural Directives](guide/structural-directives) guide.
*Attribute directives* are used as attributes of elements.
The built-in [NgStyle](guide/built-in-directives#ngstyle) directive in the
[Built-in directives](guide/built-in-directives) guide, for example,
can change several element styles at the same time.
## Build a simple attribute directive
An attribute directive minimally requires building a controller class annotated with
`@Directive`, which specifies the selector that identifies
the attribute.
The controller class implements the desired directive behavior.
This page demonstrates building a simple _appHighlight_ attribute
directive to set an element's background color
when the user hovers over that element. You can apply it like this:
<code-example path="attribute-directives/src/app/app.component.1.html" header="src/app/app.component.html (applied)" region="applied"></code-example>
{@a write-directive}
Please note that directives _do not_ support namespaces.
<code-example path="attribute-directives/src/app/app.component.avoid.html" header="src/app/app.component.avoid.html (unsupported)" region="unsupported"></code-example>
### Write the directive code
Create the directive class file in a terminal window with the CLI command [`ng generate directive`](cli/generate).
<code-example language="sh" class="code-shell">
<code-example language="sh" class="code-shell">
ng generate directive highlight
</code-example>
The CLI creates `src/app/highlight.directive.ts`, a corresponding test file `src/app/highlight.directive.spec.ts`, and _declares_ the directive class in the root `AppModule`.
The CLI creates `src/app/highlight.directive.ts`, a corresponding test file `src/app/highlight.directive.spec.ts`, and declares the directive class in the `AppModule`.
The CLI generates the default `src/app/highlight.directive.ts` as follows:
<code-example path="attribute-directives/src/app/highlight.directive.0.ts" header="src/app/highlight.directive.ts"></code-example>
The `@Directive()` decorator's configuration property specifies the directive's CSS attribute selector, `[appHighlight]`.
1. Import `ElementRef` from `@angular/core`.
`ElementRef` grants direct access to the host DOM element through its `nativeElement` property.
1. Add `ElementRef` in the directive's `constructor()` to [inject](guide/dependency-injection) a reference to the host DOM element, the element to which you apply `appHighlight`.
1. Add logic to the `HighlightDirective` class that sets the background to yellow.
<code-example path="attribute-directives/src/app/highlight.directive.1.ts" header="src/app/highlight.directive.ts"></code-example>
<div class="alert is-helpful">
_Directives_ must be declared in [Angular Modules](guide/ngmodules) in the same manner as _components_.
Directives _do not_ support namespaces.
</div >
The generated `src/app/highlight.directive.ts` is as follows:
<code-example path="attribute-directives/src/app/highlight.directive.0.ts" header="src/app/highlight.directive.ts"></code-example>
The imported `Directive` symbol provides Angular the `@Directive` decorator.
The `@Directive` decorator's lone configuration property specifies the directive's
[CSS attribute selector](https://developer.mozilla.org/docs/Web/CSS/Attribute_selectors), `[appHighlight]`.
It's the brackets (`[]`) that make it an attribute selector.
Angular locates each element in the template that has an attribute named `appHighlight` and applies the logic of this directive to that element.
The _attribute selector_ pattern explains the name of this kind of directive.
<div class="alert is-helpful">
#### Why not "highlight"?
Though *highlight* would be a more concise selector than *appHighlight* and it would work,
the best practice is to prefix selector names to ensure
they don't conflict with standard HTML attributes.
This also reduces the risk of colliding with third-party directive names.
The CLI added the `app` prefix for you.
Make sure you do **not** prefix the `highlight` directive name with **`ng`** because
that prefix is reserved for Angular and using it could cause bugs that are difficult to diagnose.
<code-example path="attribute-directives/src/app/app.component.avoid.html" header="src/app/app.component.avoid.html (unsupported)" region="unsupported"></code-example>
</div>
After the `@Directive` metadata comes the directive's controller class,
called `HighlightDirective`, which contains the (currently empty) logic for the directive.
Exporting `HighlightDirective` makes the directive accessible.
Now edit the generated `src/app/highlight.directive.ts` to look as follows:
<code-example path="attribute-directives/src/app/highlight.directive.1.ts" header="src/app/highlight.directive.ts"></code-example>
The `import` statement specifies an additional `ElementRef` symbol from the Angular `core` library:
You use the `ElementRef` in the directive's constructor
to [inject](guide/dependency-injection) a reference to the host DOM element,
the element to which you applied `appHighlight`.
`ElementRef` grants direct access to the host DOM element
through its `nativeElement` property.
This first implementation sets the background color of the host element to yellow.
{@a apply-directive}
## Applying an attribute directive
## Apply the attribute directive
1. To use the `HighlightDirective`, add a `<p>` element to the HTML template with the directive as an attribute.
To use the new `HighlightDirective`, add a paragraph (`<p>`) element to the template of the root `AppComponent` and apply the directive as an attribute.
<code-example path="attribute-directives/src/app/app.component.1.html" header="src/app/app.component.html" region="applied"></code-example>
<code-example path="attribute-directives/src/app/app.component.1.html" header="src/app/app.component.html" region="applied"></code-example>
Now run the application to see the `HighlightDirective` in action.
<code-example language="sh" class="code-shell">
ng serve
</code-example>
To summarize, Angular found the `appHighlight` attribute on the **host** `<p>` element.
It created an instance of the `HighlightDirective` class and
injected a reference to the `<p>` element into the directive's constructor
which sets the `<p>` element's background style to yellow.
Angular creates an instance of the `HighlightDirective` class and injects a reference to the `<p>` element into the directive's constructor, which sets the `<p>` element's background style to yellow.
{@a respond-to-user}
## Respond to user-initiated events
## Handling user events
Currently, `appHighlight` simply sets an element color.
The directive could be more dynamic.
It could detect when the user mouses into or out of the element
and respond by setting or clearing the highlight color.
This section shows you how to detect when a user mouses into or out of the element and to respond by setting or clearing the highlight color.
Begin by adding `HostListener` to the list of imported symbols.
1. Import `HostListener` from '@angular/core'.
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (imports)" region="imports"></code-example>
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (imports)" region="imports"></code-example>
Then add two event handlers that respond when the mouse enters or leaves,
each adorned by the `HostListener` decorator.
1. Add two event handlers that respond when the mouse enters or leaves, each with the `@HostListener()` decorator.
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (mouse-methods)" region="mouse-methods"></code-example>
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (mouse-methods)" region="mouse-methods"></code-example>
The `@HostListener` decorator lets you subscribe to events of the DOM
element that hosts an attribute directive, the `<p>` in this case.
With the `@HostListener()` decorator, you can subscribe to events of the DOM element that hosts an attribute directive, the `<p>` in this case.
<div class="alert is-helpful">
The handlers delegate to a helper method, `highlight()`, that sets the color on the host DOM element, `el`.
Of course you could reach into the DOM with standard JavaScript and attach event listeners manually.
There are at least three problems with _that_ approach:
1. You have to write the listeners correctly.
1. The code must *detach* the listener when the directive is destroyed to avoid memory leaks.
1. Talking to DOM API directly isn't a best practice.
</div>
The handlers delegate to a helper method that sets the color on the host DOM element, `el`.
The helper method, `highlight`, was extracted from the constructor.
The revised constructor simply declares the injected `el: ElementRef`.
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (constructor)" region="ctor"></code-example>
Here's the updated directive in full:
The complete directive is as follows:
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts"></code-example>
Run the app and confirm that the background color appears when
the pointer hovers over the paragraph element and disappears as the pointer moves out.
The background color appears when the pointer hovers over the paragraph element and disappears as the pointer moves out.
<div class="lightbox">
<img src="generated/images/guide/attribute-directives/highlight-directive-anim.gif" alt="Second Highlight">
</div>
{@a bindings}
## Passing values into an attribute directive
## Pass values into the directive with an _@Input_ data binding
This section walks you through setting the highlight color while applying the `HighlightDirective`.
Currently the highlight color is hard-coded _within_ the directive. That's inflexible.
In this section, you give the developer the power to set the highlight color while applying the directive.
1. In `highlight.directive.ts`, import `Input` from `@angular/core`.
Begin by adding `Input` to the list of symbols imported from `@angular/core`.
<code-example path="attribute-directives/src/app/highlight.directive.3.ts" header="src/app/highlight.directive.ts (imports)" region="imports"></code-example>
<code-example path="attribute-directives/src/app/highlight.directive.3.ts" header="src/app/highlight.directive.ts (imports)" region="imports"></code-example>
Add a `highlightColor` property to the directive class like this:
1. Add an `appHighlight` `@Input()` property.
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (highlightColor)" region="color"></code-example>
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts" region="color-2"></code-example>
{@a input}
The `@Input()` decorator adds metadata to the class that makes the directive's `appHighlight` property available for binding.
### Binding to an `@Input()` property
1. In `app.component.ts`, add a `color` property to the `AppComponent`.
Notice the `@Input()` decorator. It adds metadata to the class that makes the directive's `highlightColor` property available for binding.
<code-example path="attribute-directives/src/app/app.component.1.ts" header="src/app/app.component.ts (class)" region="class"></code-example>
It's called an *input* property because data flows from the binding expression _into_ the directive.
Without that `@Input()` metadata, Angular rejects the binding; see [below](guide/attribute-directives#why-input "Why add @Input?") for more information.
1. To simultaneously apply the directive and the color, use property binding with the `appHighlight` directive selector, setting it equal to `color`.
Try it by adding the following directive binding variations to the `AppComponent` template:
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (color)" region="color"></code-example>
<code-example path="attribute-directives/src/app/app.component.1.html" header="src/app/app.component.html (excerpt)" region="color-1"></code-example>
The `[appHighlight]` attribute binding performs two tasks:
Add a `color` property to the `AppComponent`.
* applies the highlighting directive to the `<p>` element
* sets the directive's highlight color with a property binding
<code-example path="attribute-directives/src/app/app.component.1.ts" header="src/app/app.component.ts (class)" region="class"></code-example>
### Setting the value with user input
Let it control the highlight color with a property binding.
This section guides you through adding radio buttons to bind your color choice to the `appHighlight` directive.
<code-example path="attribute-directives/src/app/app.component.1.html" header="src/app/app.component.html (excerpt)" region="color-2"></code-example>
1. Add markup to `app.component.html` for choosing a color as follows:
That's good, but it would be nice to _simultaneously_ apply the directive and set the color _in the same attribute_ like this.
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (v2)" region="v2"></code-example>
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (color)" region="color"></code-example>
1. Revise the `AppComponent.color` so that it has no initial value.
The `[appHighlight]` attribute binding both applies the highlighting directive to the `<p>` element
and sets the directive's highlight color with a property binding.
You're re-using the directive's attribute selector (`[appHighlight]`) to do both jobs.
That's a crisp, compact syntax.
<code-example path="attribute-directives/src/app/app.component.ts" header="src/app/app.component.ts (class)" region="class"></code-example>
You'll have to rename the directive's `highlightColor` property to `appHighlight` because that's now the color property binding name.
1. Serve your application to verify that the user can choose the color with the radio buttons.
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (renamed to match directive selector)" region="color-2"></code-example>
This is disagreeable. The word, `appHighlight`, is a terrible property name and it doesn't convey the property's intent.
{@a input-alias}
### Bind to an _@Input_ alias
Fortunately you can name the directive property whatever you want _and_ **_alias it_** for binding purposes.
Restore the original property name and specify the selector as the alias in the argument to `@Input()`.
<code-example path="attribute-directives/src/app/highlight.directive.ts" header="src/app/highlight.directive.ts (color property with alias)" region="color"></code-example>
_Inside_ the directive the property is known as `highlightColor`.
_Outside_ the directive, where you bind to it, it's known as `appHighlight`.
You get the best of both worlds: the property name you want and the binding syntax you want:
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (color)" region="color"></code-example>
Now that you're binding via the alias to the `highlightColor`, modify the `onMouseEnter()` method to use that property.
If someone neglects to bind to `appHighlight`, highlight the host element in red:
<code-example path="attribute-directives/src/app/highlight.directive.3.ts" header="src/app/highlight.directive.ts (mouse enter)" region="mouse-enter"></code-example>
Here's the latest version of the directive class.
<code-example path="attribute-directives/src/app/highlight.directive.3.ts" header="src/app/highlight.directive.ts (excerpt)"></code-example>
## Write a harness to try it
It may be difficult to imagine how this directive actually works.
In this section, you'll turn `AppComponent` into a harness that
lets you pick the highlight color with a radio button and bind your color choice to the directive.
Update <code>app.component.html</code> as follows:
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (v2)" region="v2"></code-example>
Revise the `AppComponent.color` so that it has no initial value.
<code-example path="attribute-directives/src/app/app.component.ts" header="src/app/app.component.ts (class)" region="class"></code-example>
Here are the harness and directive in action.
<div class="lightbox">
<img src="generated/images/guide/attribute-directives/highlight-directive-v2-anim.gif" alt="Highlight v.2">
</div>
<div class="lightbox">
<img src="generated/images/guide/attribute-directives/highlight-directive-v2-anim.gif" alt="Animated gif of the refactored highlight directive changing color according to the radio button the user selects">
</div>
{@a second-property}
## Bind to a second property
## Binding to a second property
This highlight directive has a single customizable property. In a real app, it may need more.
This section guides you through configuring your application so the developer can set the default color.
At the moment, the default color&mdash;the color that prevails until
the user picks a highlight color&mdash;is hard-coded as "red".
Let the template developer set the default color.
1. Add a second `Input()` property to `HighlightDirective` called `defaultColor`.
Add a second **input** property to `HighlightDirective` called `defaultColor`:
<code-example path="attribute-directives/src/app/highlight.directive.ts" header="src/app/highlight.directive.ts (defaultColor)" region="defaultColor"></code-example>
<code-example path="attribute-directives/src/app/highlight.directive.ts" header="src/app/highlight.directive.ts (defaultColor)" region="defaultColor"></code-example>
1. Revise the directive's `onMouseEnter` so that it first tries to highlight with the `highlightColor`, then with the `defaultColor`, and falls back to `red` if both properties are `undefined`.
Revise the directive's `onMouseEnter` so that it first tries to highlight with the `highlightColor`,
then with the `defaultColor`, and falls back to "red" if both properties are undefined.
<code-example path="attribute-directives/src/app/highlight.directive.ts" header="src/app/highlight.directive.ts (mouse-enter)" region="mouse-enter"></code-example>
<code-example path="attribute-directives/src/app/highlight.directive.ts" header="src/app/highlight.directive.ts (mouse-enter)" region="mouse-enter"></code-example>
1. To bind to the `AppComponent.color` and fall back to "violet" as the default color, add the following HTML.
In this case, the `defaultColor` binding doesn't use square brackets, `[]`, because it is static.
How do you bind to a second property when you're already binding to the `appHighlight` attribute name?
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (defaultColor)" region="defaultColor"></code-example>
As with components, you can add as many directive property bindings as you need by stringing them along in the template.
The developer should be able to write the following template HTML to both bind to the `AppComponent.color`
and fall back to "violet" as the default color.
As with components, you can add multiple directive property bindings to a host element.
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (defaultColor)" region="defaultColor"></code-example>
The default color is red if there is no default color binding.
When the user chooses a color the selected color becomes the active highlight color.
Angular knows that the `defaultColor` binding belongs to the `HighlightDirective`
because you made it _public_ with the `@Input()` decorator.
Here's how the harness should work when you're done coding.
<div class="lightbox">
<img src="generated/images/guide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight">
</div>
<div class="lightbox">
<img src="generated/images/guide/attribute-directives/highlight-directive-final-anim.gif" alt="Animated gif of final highlight directive that shows red color with no binding and violet with the default color set. When user selects color, the selection takes precedence.">
</div>
{@a ngNonBindable}
## `ngNonBindable`
With the built-in template primitive `ngNonBindable`, Angular won't
evaluate expressions in elements. For example:
## Deactivating Angular processing with `NgNonBindable`
To prevent expression evaluation in the browser, add `ngNonBindable` to the host element.
`ngNonBindable` deactivates interpolation, directives, and binding in templates.
In the following example, the expression `{{ 1 + 1 }}` renders just as it does in your code editor, and does not display `2`.
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" header="src/app/app.component.html" region="ngNonBindable"></code-example>
The expression `{{ 1 + 1 }}` will render just as it does in your code editor,
and will not display `2`. This is helpful when you want to render code in the browser.
When you apply `ngNonBindable` to an element, it stops any binding starting at that element, including child elements. However, `ngNonBindable` still allows
directives to work to the element where you apply `ngNonBindable`. In the following example, the `appHighlight` directive will still be active but Angular will not evaluate the expression `{{ 1 + 1 }}`.
Applying `ngNonBindable` to an element stops binding for that element's child elements.
However, `ngNonBindable` still allows directives to work on the element where you apply `ngNonBindable`.
In the following example, the `appHighlight` directive is still active but Angular does not evaluate the expression `{{ 1 + 1 }}`.
<code-example path="attribute-directives/src/app/app.component.html" linenums="false" header="src/app/app.component.html" region="ngNonBindable-with-directive"></code-example>
Additionally, if you apply `ngNonBindable` to a parent element, interpolation and binding of any sort, such as property binding, or event binding, is disabled for its children.
## Summary
This page covered how to:
* [Build an **attribute directive**](guide/attribute-directives#write-directive) that modifies the behavior of an element.
* [Apply the directive](guide/attribute-directives#apply-directive) to an element in a template.
* [Respond to **events**](guide/attribute-directives#respond-to-user) that change the directive's behavior.
* [**Bind** values to the directive](guide/attribute-directives#bindings).
* [Prevent expression evaluation](guide/attribute-directives#ngNonBindable).
The final source code follows:
<code-tabs>
<code-pane header="app/app.component.ts" path="attribute-directives/src/app/app.component.ts"></code-pane>
<code-pane header="app/app.component.html" path="attribute-directives/src/app/app.component.html"></code-pane>
<code-pane header="app/highlight.directive.ts" path="attribute-directives/src/app/highlight.directive.ts"></code-pane>
<code-pane header="app/app.module.ts" path="attribute-directives/src/app/app.module.ts"></code-pane>
<code-pane header="main.ts" path="attribute-directives/src/main.ts"></code-pane>
<code-pane header="index.html" path="attribute-directives/src/index.html"></code-pane>
</code-tabs>
You can also experience and download the <live-example title="Attribute Directive example"></live-example>.
{@a why-input}
### Appendix: Why add `@Input()`?
In this demo, the `highlightColor` property is an `@Input()` property of
the `HighlightDirective`. You've seen it applied without an alias:
<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (color)" region="color"></code-example>
You've seen it with an alias:
<code-example path="attribute-directives/src/app/highlight.directive.ts" header="src/app/highlight.directive.ts (color)" region="color"></code-example>
Either way, the `@Input()` decorator tells Angular that this property is
_public_ and available for binding by a parent component.
Without `@Input()`, Angular refuses to bind to the property.
You've bound template HTML to component properties before and never used `@Input()`.
What's different?
The difference is a matter of trust.
Angular treats a component's template as _belonging_ to the component.
The component and its template trust each other implicitly.
Therefore, the component's own template may bind to _any_ property of that component,
with or without the `@Input()` decorator.
But a component or directive shouldn't blindly trust _other_ components and directives.
The properties of a component or directive are hidden from binding by default.
They are _private_ from an Angular binding perspective.
When adorned with the `@Input()` decorator, the property becomes _public_ from an Angular binding perspective.
Only then can it be bound by some other component or directive.
You can tell if `@Input()` is needed by the position of the property name in a binding.
* When it appears in the template expression to the ***right*** of the equals (=),
it belongs to the template's component and does not require the `@Input()` decorator.
* When it appears in **square brackets** ([ ]) to the **left** of the equals (=),
the property belongs to some _other_ component or directive;
that property must be adorned with the `@Input()` decorator.
Now apply that reasoning to the following example:
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (color)" region="color"></code-example>
* The `color` property in the expression on the right belongs to the template's component.
The template and its component trust each other.
The `color` property doesn't require the `@Input()` decorator.
* The `appHighlight` property on the left refers to an _aliased_ property of the `HighlightDirective`,
not a property of the template's component.
For security, the directive property must carry the `@Input()` decorator.
If you apply `ngNonBindable` to a parent element, Angular disables interpolation and binding of any sort, such as property binding or event binding, for the element's children.

View File

@ -1026,6 +1026,15 @@ For example, the prefix `toh` represents **T**our **o**f **H**eroes and the pref
**Do** spell non-element selectors in lower camel case unless the selector is meant to match a native HTML attribute.
</div>
<div class="s-rule avoid">
**Don't** prefix a directive name with `ng` because that prefix is reserved for Angular and using it could cause bugs that are difficult to diagnose.
</div>