docs: add documentation for ngNonBindable (#36560)

ngNonBindable documentation was not present, on docs site added documentation for ngNonBindable. With this template primitive, Angular won't
evaluate expressions in elements.

Fixes #28577 Fixes #19497

PR Close #36560
This commit is contained in:
Ajit Singh 2020-06-14 14:23:19 +05:30 committed by atscott
parent 209a18c624
commit 806d7aa22c
2 changed files with 57 additions and 21 deletions

View File

@ -1,7 +1,7 @@
<!-- #docregion v2, --> <!-- #docregion v2, -->
<h1>My First Attribute Directive</h1> <h1>My First Attribute Directive</h1>
<h4>Pick a highlight color</h4> <h2>Pick a highlight color</h2>
<div> <div>
<input type="radio" name="colors" (click)="color='lightgreen'">Green <input type="radio" name="colors" (click)="color='lightgreen'">Green
<input type="radio" name="colors" (click)="color='yellow'">Yellow <input type="radio" name="colors" (click)="color='yellow'">Yellow
@ -17,8 +17,22 @@
</p> </p>
<!-- #enddocregion defaultColor, --> <!-- #enddocregion defaultColor, -->
<hr> <hr />
<p><i>Mouse over the following lines to see fixed highlights</i></p> <h2>Mouse over the following lines to see fixed highlights</h2>
<p [appHighlight]="'yellow'">Highlighted in yellow</p> <p [appHighlight]="'yellow'">Highlighted in yellow</p>
<p appHighlight="orange">Highlighted in orange</p> <p appHighlight="orange">Highlighted in orange</p>
<hr />
<h2>ngNonBindable</h2>
<!-- #docregion ngNonBindable -->
<p>Use ngNonBindable to stop evaluation.</p>
<p ngNonBindable>This should not evaluate: {{ 1 + 1 }}</p>
<!-- #enddocregion ngNonBindable -->
<!-- #docregion ngNonBindable-with-directive -->
<h3>ngNonBindable with a directive</h3>
<div ngNonBindable [appHighlight]="'yellow'">This should not evaluate: {{ 1 +1 }}, but will highlight yellow.
</div>
<!-- #enddocregion ngNonBindable-with-directive -->

View File

@ -195,12 +195,12 @@ Add a `highlightColor` property to the directive class like this:
{@a input} {@a input}
### Binding to an _@Input_ property ### Binding to an `@Input()` property
Notice the `@Input` decorator. It adds metadata to the class that makes the directive's `highlightColor` property available for binding. Notice the `@Input()` decorator. It adds metadata to the class that makes the directive's `highlightColor` property available for binding.
It's called an *input* property because data flows from the binding expression _into_ the directive. 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 about that. Without that `@Input()` metadata, Angular rejects the binding; see [below](guide/attribute-directives#why-input "Why add @Input?") for more information.
Try it by adding the following directive binding variations to the `AppComponent` template: Try it by adding the following directive binding variations to the `AppComponent` template:
@ -235,7 +235,7 @@ This is disagreeable. The word, `appHighlight`, is a terrible property name and
Fortunately you can name the directive property whatever you want _and_ **_alias it_** for binding purposes. 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`. 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> <code-example path="attribute-directives/src/app/highlight.directive.ts" header="src/app/highlight.directive.ts (color property with alias)" region="color"></code-example>
@ -303,7 +303,7 @@ and fall back to "violet" as the default color.
<code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (defaultColor)" region="defaultColor"></code-example> <code-example path="attribute-directives/src/app/app.component.html" header="src/app/app.component.html (defaultColor)" region="defaultColor"></code-example>
Angular knows that the `defaultColor` binding belongs to the `HighlightDirective` Angular knows that the `defaultColor` binding belongs to the `HighlightDirective`
because you made it _public_ with the `@Input` decorator. because you made it _public_ with the `@Input()` decorator.
Here's how the harness should work when you're done coding. Here's how the harness should work when you're done coding.
@ -311,6 +311,27 @@ Here's how the harness should work when you're done coding.
<img src="generated/images/guide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight"> <img src="generated/images/guide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight">
</div> </div>
<hr />
{@a ngNonBindable}
## `ngNonBindable`
With the built-in template primitive `ngNonBindable`, Angular won't
evaluate expressions in elements. For example:
<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 }}`.
<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 ## Summary
This page covered how to: This page covered how to:
@ -319,6 +340,7 @@ This page covered how to:
* [Apply the directive](guide/attribute-directives#apply-directive) to an element in a template. * [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. * [Respond to **events**](guide/attribute-directives#respond-to-user) that change the directive's behavior.
* [**Bind** values to the directive](guide/attribute-directives#bindings). * [**Bind** values to the directive](guide/attribute-directives#bindings).
* [Prevent expression evaluation](guide/attribute-directives#ngNonBindable).
The final source code follows: The final source code follows:
@ -337,9 +359,9 @@ You can also experience and download the <live-example title="Attribute Directiv
{@a why-input} {@a why-input}
### Appendix: Why add _@Input_? ### Appendix: Why add `@Input()`?
In this demo, the `highlightColor` property is an ***input*** property of In this demo, the `highlightColor` property is an `@Input()` property of
the `HighlightDirective`. You've seen it applied without an alias: 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> <code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (color)" region="color"></code-example>
@ -348,33 +370,33 @@ 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> <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 Either way, the `@Input()` decorator tells Angular that this property is
_public_ and available for binding by a parent component. _public_ and available for binding by a parent component.
Without `@Input`, Angular refuses to bind to the property. Without `@Input()`, Angular refuses to bind to the property.
You've bound template HTML to component properties before and never used `@Input`. You've bound template HTML to component properties before and never used `@Input()`.
What's different? What's different?
The difference is a matter of trust. The difference is a matter of trust.
Angular treats a component's template as _belonging_ to the component. Angular treats a component's template as _belonging_ to the component.
The component and its template trust each other implicitly. The component and its template trust each other implicitly.
Therefore, the component's own template may bind to _any_ property of that component, Therefore, the component's own template may bind to _any_ property of that component,
with or without the `@Input` decorator. with or without the `@Input()` decorator.
But a component or directive shouldn't blindly trust _other_ components and directives. 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. The properties of a component or directive are hidden from binding by default.
They are _private_ from an Angular binding perspective. They are _private_ from an Angular binding perspective.
When adorned with the `@Input` decorator, the property becomes _public_ 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. 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. 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 (=), * 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. 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 (=), * When it appears in **square brackets** ([ ]) to the **left** of the equals (=),
the property belongs to some _other_ component or directive; the property belongs to some _other_ component or directive;
that property must be adorned with the `@Input` decorator. that property must be adorned with the `@Input()` decorator.
Now apply that reasoning to the following example: Now apply that reasoning to the following example:
@ -382,8 +404,8 @@ Now apply that reasoning to the following example:
* The `color` property in the expression on the right belongs to the template's component. * The `color` property in the expression on the right belongs to the template's component.
The template and its component trust each other. The template and its component trust each other.
The `color` property doesn't require the `@Input` decorator. The `color` property doesn't require the `@Input()` decorator.
* The `appHighlight` property on the left refers to an _aliased_ property of the `HighlightDirective`, * The `appHighlight` property on the left refers to an _aliased_ property of the `HighlightDirective`,
not a property of the template's component. There are trust issues. not a property of the template's component.
Therefore, the directive property must carry the `@Input` decorator. For security, the directive property must carry the `@Input()` decorator.