Skip to content

Commit

Permalink
docs: add documentation for ngNonBindable
Browse files Browse the repository at this point in the history
Ng non bindable documentatioon was not presennt added documentation for ng non bindable

Fixes angular#28577
  • Loading branch information
ajitsinghkaler committed Apr 10, 2020
1 parent fee3161 commit 6132b9d
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!-- #docregion v2, -->
<h1>My First Attribute Directive</h1>

<h4>Pick a highlight color</h4>
<h2>Pick a highlight color</h2>
<div>
<input type="radio" name="colors" (click)="color='lightgreen'">Green
<input type="radio" name="colors" (click)="color='yellow'">Yellow
Expand All @@ -17,8 +17,22 @@ <h4>Pick a highlight color</h4>
</p>
<!-- #enddocregion defaultColor, -->

<hr>
<p><i>Mouse over the following lines to see fixed highlights</i></p>
<hr />
<h2>Mouse over the following lines to see fixed highlights</h2>

<p [appHighlight]="'yellow'">Highlighted in yellow</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 -->
58 changes: 40 additions & 18 deletions aio/content/guide/attribute-directives.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,12 @@ Add a `highlightColor` property to the directive class like this:

{@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.
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 about that.

Try it by adding the following directive binding variations to the `AppComponent` template:

Expand Down Expand Up @@ -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.

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>

Expand Down Expand Up @@ -303,14 +303,35 @@ 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>

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.

<div class="lightbox">
<img src="generated/images/guide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight">
</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`. For example, in the following, 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, will be disabled for its children.

## Summary

This page covered how to:
Expand All @@ -319,6 +340,7 @@ This page covered how to:
* [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:

Expand All @@ -337,9 +359,9 @@ You can also experience and download the <live-example title="Attribute Directiv

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

<code-example path="attribute-directives/src/app/highlight.directive.2.ts" header="src/app/highlight.directive.ts (color)" region="color"></code-example>
Expand All @@ -348,42 +370,42 @@ 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
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.
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?

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.
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.
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.
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.
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.
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 `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. There are trust issues.
Therefore, the directive property must carry the `@Input` decorator.
not a property of the template's component.
For security, the directive property must carry the `@Input()` decorator.

0 comments on commit 6132b9d

Please sign in to comment.