|
|
|
@ -1,8 +1,8 @@
|
|
|
|
|
|
|
|
|
|
# Property binding `[property]`
|
|
|
|
|
# Property binding
|
|
|
|
|
|
|
|
|
|
Use property binding to _set_ properties of target elements or
|
|
|
|
|
directive `@Input()` decorators.
|
|
|
|
|
Property binding in Angular helps you set values for properties of HTML elements or directives.
|
|
|
|
|
With property binding, you can do things such as toggle button functionality, set paths programatically, and share values between components.
|
|
|
|
|
|
|
|
|
|
<div class="alert is-helpful">
|
|
|
|
|
|
|
|
|
@ -10,34 +10,57 @@ See the <live-example></live-example> for a working example containing the code
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
## One-way in
|
|
|
|
|
## Prerequisites
|
|
|
|
|
|
|
|
|
|
Property binding flows a value in one direction,
|
|
|
|
|
from a component's property into a target element property.
|
|
|
|
|
To get the most out of property binding, you should be familiar with the following:
|
|
|
|
|
|
|
|
|
|
You can't use property
|
|
|
|
|
binding to read or pull values out of target elements. Similarly, you cannot use
|
|
|
|
|
property binding to call a method on the target element.
|
|
|
|
|
If the element raises events, you can listen to them with an [event binding](guide/event-binding).
|
|
|
|
|
* [Basics of components](guide/architecture-components)
|
|
|
|
|
* [Basics of templates](guide/glossary#template)
|
|
|
|
|
* [Binding syntax](guide/binding-syntax)
|
|
|
|
|
|
|
|
|
|
If you must read a target element property or call one of its methods,
|
|
|
|
|
see the API reference for [ViewChild](api/core/ViewChild) and
|
|
|
|
|
[ContentChild](api/core/ContentChild).
|
|
|
|
|
<hr />
|
|
|
|
|
|
|
|
|
|
## Examples
|
|
|
|
|
## Understanding the flow of data
|
|
|
|
|
|
|
|
|
|
The most common property binding sets an element property to a component
|
|
|
|
|
property value. An example is
|
|
|
|
|
binding the `src` property of an image element to a component's `itemImageUrl` property:
|
|
|
|
|
Property binding moves a value in one direction, from a component's property into a target element property.
|
|
|
|
|
|
|
|
|
|
<div class="alert is-helpful">
|
|
|
|
|
|
|
|
|
|
For more information on listening for events, see [Event binding](guide/event-binding).
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
To read a target element property or call one of its methods, see the API reference for [ViewChild](api/core/ViewChild) and [ContentChild](api/core/ContentChild).
|
|
|
|
|
|
|
|
|
|
## Binding to a property
|
|
|
|
|
|
|
|
|
|
To bind to an element's property, enclose it in square brackets, `[]`, which identifies the property as a target property.
|
|
|
|
|
A target property is the DOM property to which you want to assign a value.
|
|
|
|
|
For example, the target property in the following code is the image element's `src` property.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="property-binding" header="src/app/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
Here's an example of binding to the `colSpan` property. Notice that it's not `colspan`,
|
|
|
|
|
which is the attribute, spelled with a lowercase `s`.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="colSpan" header="src/app/app.component.html"></code-example>
|
|
|
|
|
In most cases, the target name is the name of a property, even when it appears to be the name of an attribute.
|
|
|
|
|
In this example, `src` is the name of the `<img>` element property.
|
|
|
|
|
|
|
|
|
|
For more details, see the [MDN HTMLTableCellElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) documentation.
|
|
|
|
|
The brackets, `[]`, cause Angular to evaluate the right-hand side of the assignment as a dynamic expression.
|
|
|
|
|
Without the brackets, Angular treats the the right-hand side as a string literal and sets the property to that static value.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="no-evaluation" header="src/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
Omitting the brackets renders the string `parentItem`, not the value of `parentItem`.
|
|
|
|
|
|
|
|
|
|
## Setting an element property to a component property value
|
|
|
|
|
|
|
|
|
|
To bind the `src` property of an `<img>` element to a component's property, place the target, `src`, in square brackets followed by an equal sign and then the property.
|
|
|
|
|
The property here is `itemImageUrl`.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="property-binding" header="src/app/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
Declare the `itemImageUrl` property in the class, in this case `AppComponent`.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.ts" region="item-image" header="src/app/app.component.ts"></code-example>
|
|
|
|
|
|
|
|
|
|
{@a colspan}
|
|
|
|
|
|
|
|
|
@ -81,175 +104,100 @@ for parent and child components to communicate:
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="model-property-binding" header="src/app/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
## Binding targets
|
|
|
|
|
|
|
|
|
|
An element property between enclosing square brackets identifies the target property.
|
|
|
|
|
The target property in the following code is the image element's `src` property.
|
|
|
|
|
## Toggling button functionality
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="property-binding" header="src/app/app.component.html"></code-example>
|
|
|
|
|
To disable a button's functionality depending on a Boolean value, bind the DOM `disabled` property to a property in the class that is `true` or `false`.
|
|
|
|
|
|
|
|
|
|
There's also the `bind-` prefix alternative:
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="disabled-button" header="src/app/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="bind-prefix" header="src/app/app.component.html"></code-example>
|
|
|
|
|
Because the value of the property `isUnchanged` is `true` in the `AppComponent`, Angular disables the button.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.ts" region="boolean" header="src/app/app.component.ts"></code-example>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
In most cases, the target name is the name of a property, even
|
|
|
|
|
when it appears to be the name of an attribute.
|
|
|
|
|
So in this case, `src` is the name of the `<img>` element property.
|
|
|
|
|
## Setting a directive property
|
|
|
|
|
|
|
|
|
|
Element properties may be the more common targets,
|
|
|
|
|
but Angular looks first to see if the name is a property of a known directive,
|
|
|
|
|
as it is in the following example:
|
|
|
|
|
To set a property of a directive, place the directive within square brackets , such as `[ngClass]`, followed by an equal sign and the property.
|
|
|
|
|
Here, the property is `classes`.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="class-binding" header="src/app/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
Technically, Angular is matching the name to a directive `@Input()`,
|
|
|
|
|
one of the property names listed in the directive's `inputs` array
|
|
|
|
|
or a property decorated with `@Input()`.
|
|
|
|
|
Such inputs map to the directive's own properties.
|
|
|
|
|
To use the property, you must declare it in the class, which in this example is `AppComponent`.
|
|
|
|
|
The value of `classes` is `special`.
|
|
|
|
|
|
|
|
|
|
If the name fails to match a property of a known directive or element, Angular reports an “unknown directive” error.
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.ts" region="directive-property" header="src/app/app.component.ts"></code-example>
|
|
|
|
|
|
|
|
|
|
<div class="alert is-helpful">
|
|
|
|
|
Angular applies the class `special` to the `<p>` element so that you can use `special` to apply CSS styles.
|
|
|
|
|
|
|
|
|
|
Though the target name is usually the name of a property,
|
|
|
|
|
there is an automatic attribute-to-property mapping in Angular for
|
|
|
|
|
several common attributes. These include `class`/`className`, `innerHtml`/`innerHTML`, and
|
|
|
|
|
`tabindex`/`tabIndex`.
|
|
|
|
|
## Bind values between components
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Avoid side effects
|
|
|
|
|
|
|
|
|
|
Evaluation of a template expression should have no visible side effects.
|
|
|
|
|
The expression language itself, or the way you write template expressions,
|
|
|
|
|
helps to a certain extent;
|
|
|
|
|
you can't assign a value to anything in a property binding expression
|
|
|
|
|
nor use the increment and decrement operators.
|
|
|
|
|
|
|
|
|
|
For example, you could have an expression that invoked a property or method that had
|
|
|
|
|
side effects. The expression could call something like `getFoo()` where only you
|
|
|
|
|
know what `getFoo()` does. If `getFoo()` changes something
|
|
|
|
|
and you happen to be binding to that something,
|
|
|
|
|
Angular may or may not display the changed value. Angular may detect the
|
|
|
|
|
change and throw a warning error.
|
|
|
|
|
As a best practice, stick to properties and to methods that return
|
|
|
|
|
values and avoid side effects.
|
|
|
|
|
|
|
|
|
|
## Return the proper type
|
|
|
|
|
|
|
|
|
|
The template expression should evaluate to the type of value
|
|
|
|
|
that the target property expects.
|
|
|
|
|
Return a string if the target property expects a string, a number if it
|
|
|
|
|
expects a number, an object if it expects an object, and so on.
|
|
|
|
|
|
|
|
|
|
In the following example, the `childItem` property of the `ItemDetailComponent` expects a string, which is exactly what you're sending in the property binding:
|
|
|
|
|
To set the model property of a custom component, place the target, here `childItem`, between square brackets `[]` followed by an equal sign and the property.
|
|
|
|
|
Here, the property is `parentItem`.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="model-property-binding" header="src/app/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
You can confirm this by looking in the `ItemDetailComponent` where the `@Input` type is set to a string:
|
|
|
|
|
<code-example path="property-binding/src/app/item-detail/item-detail.component.ts" region="input-type" header="src/app/item-detail/item-detail.component.ts (setting the @Input() type)"></code-example>
|
|
|
|
|
To use the target and the property, you must declare them in their respective classes.
|
|
|
|
|
|
|
|
|
|
Declare the target of `childItem` in its component class, in this case `ItemDetailComponent`.
|
|
|
|
|
|
|
|
|
|
For example, the following code declares the target of `childItem` in its component class, in this case `ItemDetailComponent`.
|
|
|
|
|
|
|
|
|
|
Then, the code contains an `@Input()` decorator with the `childItem` property so data can flow into it.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/item-detail/item-detail.component.ts" region="input-type" header="src/app/item-detail/item-detail.component.ts"></code-example>
|
|
|
|
|
|
|
|
|
|
Next, the code declares the property of `parentItem` in its component class, in this case `AppComponent`.
|
|
|
|
|
In this example the type of `childItem` is `string`, so `parentItem` needs to be a string.
|
|
|
|
|
Here, `parentItem` has the string value of `lamp`.
|
|
|
|
|
|
|
|
|
|
As you can see here, the `parentItem` in `AppComponent` is a string, which the `ItemDetailComponent` expects:
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.ts" region="parent-data-type" header="src/app/app.component.ts"></code-example>
|
|
|
|
|
|
|
|
|
|
### Passing in an object
|
|
|
|
|
With this configuration, the view of `<app-item-detail>` uses the value of `lamp` for `childItem`.
|
|
|
|
|
|
|
|
|
|
The previous simple example showed passing in a string. To pass in an object,
|
|
|
|
|
the syntax and thinking are the same.
|
|
|
|
|
## Property binding and security
|
|
|
|
|
|
|
|
|
|
In this scenario, `ItemListComponent` is nested within `AppComponent` and the `items` property expects an array of objects.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="pass-object" header="src/app/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
The `items` property is declared in the `ItemListComponent` with a type of `Item` and decorated with `@Input()`:
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/item-list/item-list.component.ts" region="item-input" header="src/app/item-list.component.ts"></code-example>
|
|
|
|
|
|
|
|
|
|
In this sample app, an `Item` is an object that has two properties; an `id` and a `name`.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/item.ts" region="item-class" header="src/app/item.ts"></code-example>
|
|
|
|
|
|
|
|
|
|
While a list of items exists in another file, `mock-items.ts`, you can
|
|
|
|
|
specify a different item in `app.component.ts` so that the new item will render:
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.ts" region="pass-object" header="src/app.component.ts"></code-example>
|
|
|
|
|
|
|
|
|
|
You just have to make sure, in this case, that you're supplying an array of objects because that's the type of `Item` and is what the nested component, `ItemListComponent`, expects.
|
|
|
|
|
|
|
|
|
|
In this example, `AppComponent` specifies a different `item` object
|
|
|
|
|
(`currentItems`) and passes it to the nested `ItemListComponent`. `ItemListComponent` was able to use `currentItems` because it matches what an `Item` object is according to `item.ts`. The `item.ts` file is where
|
|
|
|
|
`ItemListComponent` gets its definition of an `item`.
|
|
|
|
|
|
|
|
|
|
## Remember the brackets
|
|
|
|
|
|
|
|
|
|
The brackets, `[]`, tell Angular to evaluate the template expression.
|
|
|
|
|
If you omit the brackets, Angular treats the string as a constant
|
|
|
|
|
and *initializes the target property* with that string:
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="no-evaluation" header="src/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Omitting the brackets will render the string
|
|
|
|
|
`parentItem`, not the value of `parentItem`.
|
|
|
|
|
|
|
|
|
|
## One-time string initialization
|
|
|
|
|
|
|
|
|
|
You *should* omit the brackets when all of the following are true:
|
|
|
|
|
|
|
|
|
|
* The target property accepts a string value.
|
|
|
|
|
* The string is a fixed value that you can put directly into the template.
|
|
|
|
|
* This initial value never changes.
|
|
|
|
|
|
|
|
|
|
You routinely initialize attributes this way in standard HTML, and it works
|
|
|
|
|
just as well for directive and component property initialization.
|
|
|
|
|
The following example initializes the `prefix` property of the `StringInitComponent` to a fixed string,
|
|
|
|
|
not a template expression. Angular sets it and forgets about it.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="string-init" header="src/app/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
The `[item]` binding, on the other hand, remains a live binding to the component's `currentItems` property.
|
|
|
|
|
|
|
|
|
|
## Property binding vs. interpolation
|
|
|
|
|
|
|
|
|
|
You often have a choice between interpolation and property binding.
|
|
|
|
|
The following binding pairs do the same thing:
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="property-binding-interpolation" header="src/app/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
Interpolation is a convenient alternative to property binding in
|
|
|
|
|
many cases. When rendering data values as strings, there is no
|
|
|
|
|
technical reason to prefer one form to the other, though readability
|
|
|
|
|
tends to favor interpolation. However, *when setting an element
|
|
|
|
|
property to a non-string data value, you must use property binding*.
|
|
|
|
|
|
|
|
|
|
## Content security
|
|
|
|
|
|
|
|
|
|
Imagine the following malicious content.
|
|
|
|
|
Property binding can help keep content secure.
|
|
|
|
|
For example, consider the following malicious content.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.ts" region="malicious-content" header="src/app/app.component.ts"></code-example>
|
|
|
|
|
|
|
|
|
|
In the component template, the content might be used with interpolation:
|
|
|
|
|
The component template interpolates the content as follows:
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="malicious-interpolated" header="src/app/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
Fortunately, Angular data binding is on alert for dangerous HTML. In the above case,
|
|
|
|
|
the HTML displays as is, and the Javascript does not execute. Angular **does not**
|
|
|
|
|
allow HTML with script tags to leak into the browser, neither with interpolation
|
|
|
|
|
nor property binding.
|
|
|
|
|
|
|
|
|
|
In the following example, however, Angular [sanitizes](guide/security#sanitization-and-security-contexts)
|
|
|
|
|
the values before displaying them.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="malicious-content" header="src/app/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
Interpolation handles the `<script>` tags differently than
|
|
|
|
|
property binding but both approaches render the
|
|
|
|
|
content harmlessly. The following is the browser output
|
|
|
|
|
of the `evilTitle` examples.
|
|
|
|
|
The browser doesn't process the HTML and instead displays it raw, as follows.
|
|
|
|
|
|
|
|
|
|
<code-example language="bash">
|
|
|
|
|
"Template <script>alert("evil never sleeps")</script> Syntax" is the interpolated evil title.
|
|
|
|
|
</code-example>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Angular does not allow HTML with `<script>` tags, neither with [interpolation](guide/interpolation) nor property binding, which prevents the JavaScript from running.
|
|
|
|
|
|
|
|
|
|
In the following example, however, Angular [sanitizes](guide/security#sanitization-and-security-contexts) the values before displaying them.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="malicious-content" header="src/app/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
Interpolation handles the `<script>` tags differently than property binding, but both approaches render the content harmlessly.
|
|
|
|
|
The following is the browser output of the sanitized `evilTitle` example.
|
|
|
|
|
|
|
|
|
|
<code-example language="bash">
|
|
|
|
|
"Template Syntax" is the property bound evil title.
|
|
|
|
|
</code-example>
|
|
|
|
|
|
|
|
|
|
## Property binding and interpolation
|
|
|
|
|
|
|
|
|
|
Often [interpolation](guide/interpolation) and property binding can achieve the same results.
|
|
|
|
|
The following binding pairs do the same thing.
|
|
|
|
|
|
|
|
|
|
<code-example path="property-binding/src/app/app.component.html" region="property-binding-interpolation" header="src/app/app.component.html"></code-example>
|
|
|
|
|
|
|
|
|
|
You can use either form when rendering data values as strings, though interpolation is preferable for readability.
|
|
|
|
|
However, when setting an element property to a non-string data value, you must use property binding.
|
|
|
|
|
|
|
|
|
|
<hr />
|
|
|
|
|
|
|
|
|
|
## What's next
|
|
|
|
|
|
|
|
|
|
* [Property binding best practices](guide/property-binding-best-practices)
|
|
|
|
|