docs: edit attribute-binding doc and move colSpan note to property binding (#38860)
This commit edits the copy of the attribute binding documentation, moves the colspan section that is primarily about property binding to the property binding document, and adds a docregion to the attribute-binding example to help clarify a point in the document. Part of the copy edit reformats the style precedence list in tabular format so that it is easier to read and understand. PR Close #38860
This commit is contained in:
parent
492e236ae6
commit
4dc8d83d84
|
@ -406,6 +406,7 @@ groups:
|
||||||
'aio/content/guide/structural-directives.md',
|
'aio/content/guide/structural-directives.md',
|
||||||
'aio/content/examples/structural-directives/**',
|
'aio/content/examples/structural-directives/**',
|
||||||
'aio/content/guide/svg-in-templates.md',
|
'aio/content/guide/svg-in-templates.md',
|
||||||
|
'aio/content/guide/style-precedence.md',
|
||||||
'aio/content/images/guide/structural-directives/**',
|
'aio/content/images/guide/structural-directives/**',
|
||||||
'aio/content/guide/template-statements.md',
|
'aio/content/guide/template-statements.md',
|
||||||
'aio/content/guide/user-input.md',
|
'aio/content/guide/user-input.md',
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
<h2>Attribute binding</h2>
|
<h2>Attribute binding</h2>
|
||||||
<!-- #docregion attrib-binding-colspan -->
|
<!-- #docregion attrib-binding-colspan -->
|
||||||
<table border=1>
|
<table border=1>
|
||||||
|
<!-- #docregion colspan -->
|
||||||
<!-- expression calculates colspan=2 -->
|
<!-- expression calculates colspan=2 -->
|
||||||
<tr><td [attr.colspan]="1 + 1">One-Two</td></tr>
|
<tr><td [attr.colspan]="1 + 1">One-Two</td></tr>
|
||||||
|
<!-- #enddocregion colspan -->
|
||||||
|
|
||||||
<!-- ERROR: There is no `colspan` property to set!
|
<!-- ERROR: There is no `colspan` property to set!
|
||||||
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
|
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
|
||||||
|
@ -32,31 +34,31 @@
|
||||||
<!-- #docregion basic-specificity -->
|
<!-- #docregion basic-specificity -->
|
||||||
<h3>Basic specificity</h3>
|
<h3>Basic specificity</h3>
|
||||||
|
|
||||||
<!-- The `class.special` binding will override any value for the `special` class in `classExpr`. -->
|
<!-- The `class.special` binding overrides any value for the `special` class in `classExpression`. -->
|
||||||
<div [class.special]="isSpecial" [class]="classExpr">Some text.</div>
|
<div [class.special]="isSpecial" [class]="classExpression">Some text.</div>
|
||||||
|
|
||||||
<!-- The `style.color` binding will override any value for the `color` property in `styleExpr`. -->
|
<!-- The `style.color` binding overrides any value for the `color` property in `styleExpression`. -->
|
||||||
<div [style.color]="color" [style]="styleExpr">Some text.</div>
|
<div [style.color]="color" [style]="styleExpression">Some text.</div>
|
||||||
<!-- #enddocregion basic-specificity -->
|
<!-- #enddocregion basic-specificity -->
|
||||||
|
|
||||||
<!-- #docregion source-specificity -->
|
<!-- #docregion source-specificity -->
|
||||||
<h3>Source specificity</h3>
|
<h3>Source specificity</h3>
|
||||||
|
|
||||||
<!-- The `class.special` template binding will override any host binding to the `special` class set by `dirWithClassBinding` or `comp-with-host-binding`.-->
|
<!-- The `class.special` template binding overrides any host binding to the `special` class set by `dirWithClassBinding` or `comp-with-host-binding`.-->
|
||||||
<comp-with-host-binding [class.special]="isSpecial" dirWithClassBinding>Some text.</comp-with-host-binding>
|
<comp-with-host-binding [class.special]="isSpecial" dirWithClassBinding>Some text.</comp-with-host-binding>
|
||||||
|
|
||||||
<!-- The `style.color` template binding will override any host binding to the `color` property set by `dirWithStyleBinding` or `comp-with-host-binding`. -->
|
<!-- The `style.color` template binding overrides any host binding to the `color` property set by `dirWithStyleBinding` or `comp-with-host-binding`. -->
|
||||||
<comp-with-host-binding [style.color]="color" dirWithStyleBinding>Some text.</comp-with-host-binding>
|
<comp-with-host-binding [style.color]="color" dirWithStyleBinding>Some text.</comp-with-host-binding>
|
||||||
<!-- #enddocregion source-specificity -->
|
<!-- #enddocregion source-specificity -->
|
||||||
|
|
||||||
<!-- #docregion dynamic-priority -->
|
<!-- #docregion dynamic-priority -->
|
||||||
<h3>Dynamic vs static</h3>
|
<h3>Dynamic vs static</h3>
|
||||||
|
|
||||||
<!-- If `classExpr` has a value for the `special` class, this value will override the `class="special"` below -->
|
<!-- If `classExpression` has a value for the `special` class, this value overrides the `class="special"` below -->
|
||||||
<div class="special" [class]="classExpr">Some text.</div>
|
<div class="special" [class]="classExpression">Some text.</div>
|
||||||
|
|
||||||
<!-- If `styleExpr` has a value for the `color` property, this value will override the `style="color: blue"` below -->
|
<!-- If `styleExpression` has a value for the `color` property, this value overrides the `style="color: blue"` below -->
|
||||||
<div style="color: blue" [style]="styleExpr">Some text.</div>
|
<div style="color: blue" [style]="styleExpression">Some text.</div>
|
||||||
|
|
||||||
<!-- #enddocregion dynamic-priority -->
|
<!-- #enddocregion dynamic-priority -->
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ export class AppComponent {
|
||||||
actionName = 'Go for it';
|
actionName = 'Go for it';
|
||||||
isSpecial = true;
|
isSpecial = true;
|
||||||
canSave = true;
|
canSave = true;
|
||||||
classExpr = 'special clearance';
|
classExpression = 'special clearance';
|
||||||
styleExpr = 'color: red';
|
styleExpression = 'color: red';
|
||||||
color = 'blue';
|
color = 'blue';
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,9 @@ export class CompWithHostBindingComponent {
|
||||||
@HostBinding('style.color')
|
@HostBinding('style.color')
|
||||||
color = 'green';
|
color = 'green';
|
||||||
|
|
||||||
|
// #docregion hostbinding
|
||||||
@HostBinding('style.width')
|
@HostBinding('style.width')
|
||||||
width = '200px';
|
width = '200px';
|
||||||
|
// #enddocregion hostbinding
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Attribute, class, and style bindings
|
# Attribute, class, and style bindings
|
||||||
|
|
||||||
The template syntax provides specialized one-way bindings for scenarios less well-suited to property binding.
|
Attribute binding in Angular helps you set values for attributes directly.
|
||||||
|
With attribute binding, you can improve accessibility, style your application dynamically, and manage multiple CSS classes or styles simultaneously.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
@ -8,23 +9,36 @@ See the <live-example></live-example> for a working example containing the code
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
## Binding to an attribute
|
||||||
|
|
||||||
## Attribute binding
|
It is recommended that you set an element property with a [property binding](guide/property-binding) whenever possible.
|
||||||
|
However, sometimes you don't have an element property to bind.
|
||||||
|
In those situations, you can use attribute binding.
|
||||||
|
|
||||||
Set the value of an attribute directly with an **attribute binding**. This is the only exception to the rule that a binding sets a target property and the only binding that creates and sets an attribute.
|
For example, [ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) and
|
||||||
|
[SVG](https://developer.mozilla.org/en-US/docs/Web/SVG) are purely attributes.
|
||||||
|
Neither ARIA nor SVG correspond to element properties and don't set element properties.
|
||||||
|
In these cases, you must use attribute binding because there are no corresponding property targets.
|
||||||
|
|
||||||
Usually, setting an element property with a [property binding](guide/property-binding)
|
|
||||||
is preferable to setting the attribute with a string. However, sometimes
|
|
||||||
there is no element property to bind, so attribute binding is the solution.
|
|
||||||
|
|
||||||
Consider the [ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) and
|
## Syntax
|
||||||
[SVG](https://developer.mozilla.org/en-US/docs/Web/SVG). They are purely attributes, don't correspond to element properties, and don't set element properties. In these cases, there are no property targets to bind to.
|
|
||||||
|
|
||||||
Attribute binding syntax resembles property binding, but
|
Attribute binding syntax resembles [property binding](guide/property-binding), but instead of an element property between brackets, you precede the name of the attribute with the prefix `attr`, followed by a dot.
|
||||||
instead of an element property between brackets, start with the prefix `attr`,
|
Then, you set the attribute value with an expression that resolves to a string.
|
||||||
followed by a dot (`.`), and the name of the attribute.
|
|
||||||
You then set the attribute value, using an expression that resolves to a string,
|
<code-example language="html">
|
||||||
or remove the attribute when the expression resolves to `null`.
|
|
||||||
|
<p [attr.attribute-you-are-targeting]="expression"></p>
|
||||||
|
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
When the expression resolves to `null`, Angular removes the attribute altogether.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Binding ARIA attributes
|
||||||
|
|
||||||
One of the primary use cases for attribute binding
|
One of the primary use cases for attribute binding
|
||||||
is to set ARIA attributes, as in this example:
|
is to set ARIA attributes, as in this example:
|
||||||
|
@ -33,32 +47,30 @@ is to set ARIA attributes, as in this example:
|
||||||
|
|
||||||
{@a colspan}
|
{@a colspan}
|
||||||
|
|
||||||
|
## Binding to `colspan`
|
||||||
|
|
||||||
|
Another common use case for attribute binding is with the `colspan` attribute in tables.
|
||||||
|
Binding to the `colspan` attribute helps you keep your tables programmatically dynamic.
|
||||||
|
Depending on the amount of data that your application populates a table with, the number of columns that a row spans could change.
|
||||||
|
|
||||||
|
To use attribute binding with the `<td>` attribute `colspan`:
|
||||||
|
|
||||||
|
1. Specify the `colspan` attribute by using the following syntax: `[attr.colspan]`.
|
||||||
|
1. Set `[attr.colspan]` equal to an expression.
|
||||||
|
|
||||||
|
In the following example, binds the `colspan` attribute to the expression `1 + 1`.
|
||||||
|
|
||||||
|
<code-example path="attribute-binding/src/app/app.component.html" region="colspan" header="src/app/app.component.html"></code-example>
|
||||||
|
|
||||||
|
This binding causes the `<tr>` to span two columns.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
#### `colspan` and `colSpan`
|
Sometimes there are differences between the name of property and an attribute.
|
||||||
|
|
||||||
Notice the difference between the `colspan` attribute and the `colSpan` property.
|
`colspan` is an attribute of `<tr>`, while `colSpan` with a capital "S" is a property.
|
||||||
|
When using attribute binding, use `colspan` with a lowercase "s".
|
||||||
If you wrote something like this:
|
For more information on how to bind to the `colSpan` property, see the [`colspan` and `colSpan`](guide/property-binding#colspan) section of [Property Binding](guide/property-binding).
|
||||||
|
|
||||||
<code-example language="html">
|
|
||||||
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
You'd get this error:
|
|
||||||
|
|
||||||
<code-example language="bash">
|
|
||||||
Template parse errors:
|
|
||||||
Can't bind to 'colspan' since it isn't a known native property
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
As the message says, the `<td>` element does not have a `colspan` property. This is true
|
|
||||||
because `colspan` is an attribute—`colSpan`, with a capital `S`, is the
|
|
||||||
corresponding property. Interpolation and property binding can set only *properties*, not attributes.
|
|
||||||
|
|
||||||
Instead, you'd use property binding and write it like this:
|
|
||||||
|
|
||||||
<code-example path="attribute-binding/src/app/app.component.html" region="colSpan" header="src/app/app.component.html"></code-example>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -66,28 +78,32 @@ Instead, you'd use property binding and write it like this:
|
||||||
|
|
||||||
{@a class-binding}
|
{@a class-binding}
|
||||||
|
|
||||||
## Class binding
|
## Binding to the `class` attribute
|
||||||
|
|
||||||
Here's how to set the `class` attribute without a binding in plain HTML:
|
You can use class binding to add and remove CSS class names from an element's `class` attribute.
|
||||||
|
|
||||||
```html
|
### Binding to a single CSS `class`
|
||||||
<!-- standard class attribute setting -->
|
|
||||||
<div class="foo bar">Some text</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also add and remove CSS class names from an element's `class` attribute with a **class binding**.
|
To create a single class binding, use the prefix `class` followed by a dot and the name of the CSS class—for example, `[class.sale]="onSale"`.
|
||||||
|
Angular adds the class when the bound expression, `onSale` is truthy, and it removes the class when the expression is falsy—with the exception of `undefined`.
|
||||||
|
See [styling delegation](guide/style-precedence#styling-delegation) for more information.
|
||||||
|
|
||||||
To create a single class binding, start with the prefix `class` followed by a dot (`.`) and the name of the CSS class (for example, `[class.foo]="hasFoo"`).
|
### Binding to multiple CSS classes
|
||||||
Angular adds the class when the bound expression is truthy, and it removes the class when the expression is falsy (with the exception of `undefined`, see [styling delegation](#styling-delegation)).
|
|
||||||
|
|
||||||
To create a binding to multiple classes, use a generic `[class]` binding without the dot (for example, `[class]="classExpr"`).
|
To bind to multiple classes, use `[class]` set to an expression—for example, `[class]="classExpression"`.
|
||||||
The expression can be a space-delimited string of class names, or you can format it as an object with class names as the keys and truthy/falsy expressions as the values.
|
The expression can be a space-delimited string of class names, or an object with class names as the keys and truthy or falsy expressions as the values.
|
||||||
With object format, Angular will add a class only if its associated value is truthy.
|
With an object format, Angular adds a class only if its associated value is truthy.
|
||||||
|
|
||||||
It's important to note that with any object-like expression (`object`, `Array`, `Map`, `Set`, etc), the identity of the object must change for the class list to be updated.
|
<div class="alert is-important">
|
||||||
Updating the property without changing object identity will have no effect.
|
|
||||||
|
|
||||||
If there are multiple bindings to the same class name, conflicts are resolved using [styling precedence](#styling-precedence).
|
With any object-like expression—such as `object`, `Array`, `Map`, or `Set`—the identity of the object must change for Angular to update the class list.
|
||||||
|
Updating the property without changing object identity has no effect.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
If there are multiple bindings to the same class name, Angular uses [styling precedence](guide/style-precedence) to determine which binding to use.
|
||||||
|
|
||||||
|
The following table summarizes class binding syntax.
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
td, th {vertical-align: top}
|
td, th {vertical-align: top}
|
||||||
|
@ -118,13 +134,13 @@ If there are multiple bindings to the same class name, conflicts are resolved us
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Single class binding</td>
|
<td>Single class binding</td>
|
||||||
<td><code>[class.foo]="hasFoo"</code></td>
|
<td><code>[class.sale]="onSale"</code></td>
|
||||||
<td><code>boolean | undefined | null</code></td>
|
<td><code>boolean | undefined | null</code></td>
|
||||||
<td><code>true</code>, <code>false</code></td>
|
<td><code>true</code>, <code>false</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan=3>Multi-class binding</td>
|
<td rowspan=3>Multi-class binding</td>
|
||||||
<td rowspan=3><code>[class]="classExpr"</code></td>
|
<td rowspan=3><code>[class]="classExpression"</code></td>
|
||||||
<td><code>string</code></td>
|
<td><code>string</code></td>
|
||||||
<td><code>"my-class-1 my-class-2 my-class-3"</code></td>
|
<td><code>"my-class-1 my-class-2 my-class-3"</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -138,44 +154,44 @@ If there are multiple bindings to the same class name, conflicts are resolved us
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
The [NgClass](guide/built-in-directives/#ngclass) directive can be used as an alternative to direct `[class]` bindings.
|
|
||||||
However, using the above class binding syntax without `NgClass` is preferred because due to improvements in class binding in Angular, `NgClass` no longer provides significant value, and might eventually be removed in the future.
|
|
||||||
|
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
## Style binding
|
{@a style-binding}
|
||||||
|
|
||||||
Here's how to set the `style` attribute without a binding in plain HTML:
|
## Binding to the style attribute
|
||||||
|
|
||||||
```html
|
You can use style binding to set styles dynamically.
|
||||||
<!-- standard style attribute setting -->
|
|
||||||
<div style="color: blue">Some text</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also set styles dynamically with a **style binding**.
|
### Binding to a single style
|
||||||
|
|
||||||
To create a single style binding, start with the prefix `style` followed by a dot (`.`) and the name of the CSS style property (for example, `[style.width]="width"`).
|
To create a single style binding, use the prefix `style` followed by a dot and the name of the CSS style property—for example, `[style.width]="width"`.
|
||||||
The property will be set to the value of the bound expression, which is normally a string.
|
Angular sets the property to the value of the bound expression, which is usually a string.
|
||||||
Optionally, you can add a unit extension like `em` or `%`, which requires a number type.
|
Optionally, you can add a unit extension like `em` or `%`, which requires a number type.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
Note that a _style property_ name can be written in either
|
You can write a style property name in either [dash-case](guide/glossary#dash-case), or
|
||||||
[dash-case](guide/glossary#dash-case), as shown above, or
|
[camelCase](guide/glossary#camelcase).
|
||||||
[camelCase](guide/glossary#camelcase), such as `fontSize`.
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
If there are multiple styles you'd like to toggle, you can bind to the `[style]` property directly without the dot (for example, `[style]="styleExpr"`).
|
### Binding to multiple styles
|
||||||
The expression attached to the `[style]` binding is most often a string list of styles like `"width: 100px; height: 100px;"`.
|
|
||||||
|
|
||||||
You can also format the expression as an object with style names as the keys and style values as the values, like `{width: '100px', height: '100px'}`.
|
To toggle multiple styles, bind to the `[style]` attribute—for example, `[style]="styleExpression"`).
|
||||||
It's important to note that with any object-like expression (`object`, `Array`, `Map`, `Set`, etc), the identity of the object must change for the class list to be updated.
|
The expression is often a string list of styles such as `"width: 100px; height: 100px;"`.
|
||||||
Updating the property without changing object identity will have no effect.
|
|
||||||
|
|
||||||
If there are multiple bindings to the same style property, conflicts are resolved using [styling precedence rules](#styling-precedence).
|
You can also format the expression as an object with style names as the keys and style values as the values, such as `{width: '100px', height: '100px'}`.
|
||||||
|
|
||||||
|
<div class="alert is-important">
|
||||||
|
|
||||||
|
With any object-like expression—such as `object`, `Array`, `Map`, or `Set`—the identity of the object must change for Angular to update the class list.
|
||||||
|
Updating the property without changing object identity has no effect.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
If there are multiple bindings to the same style attribute, Angular uses [styling precedence](guide/style-precedence) to determine which binding to use.
|
||||||
|
|
||||||
|
The following table summarizes style binding syntax.
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
td, th {vertical-align: top}
|
td, th {vertical-align: top}
|
||||||
|
@ -219,7 +235,7 @@ If there are multiple bindings to the same style property, conflicts are resolve
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan=3>Multi-style binding</td>
|
<td rowspan=3>Multi-style binding</td>
|
||||||
<td rowspan=3><code>[style]="styleExpr"</code></td>
|
<td rowspan=3><code>[style]="styleExpression"</code></td>
|
||||||
<td><code>string</code></td>
|
<td><code>string</code></td>
|
||||||
<td><code>"width: 100px; height: 100px"</code></td>
|
<td><code>"width: 100px; height: 100px"</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -232,72 +248,3 @@ If there are multiple bindings to the same style property, conflicts are resolve
|
||||||
<td><code>['width', '100px']</code></td>
|
<td><code>['width', '100px']</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
The [NgStyle](guide/built-in-directives/#ngstyle) directive can be used as an alternative to direct `[style]` bindings.
|
|
||||||
However, using the above style binding syntax without `NgStyle` is preferred because due to improvements in style binding in Angular, `NgStyle` no longer provides significant value, and might eventually be removed in the future.
|
|
||||||
|
|
||||||
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
{@a styling-precedence}
|
|
||||||
|
|
||||||
## Styling Precedence
|
|
||||||
|
|
||||||
A single HTML element can have its CSS class list and style values bound to multiple sources (for example, host bindings from multiple directives).
|
|
||||||
|
|
||||||
When there are multiple bindings to the same class name or style property, Angular uses a set of precedence rules to resolve conflicts and determine which classes or styles are ultimately applied to the element.
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
<h4>Styling precedence (highest to lowest)</h4>
|
|
||||||
|
|
||||||
1. Template bindings
|
|
||||||
1. Property binding (for example, `<div [class.foo]="hasFoo">` or `<div [style.color]="color">`)
|
|
||||||
1. Map binding (for example, `<div [class]="classExpr">` or `<div [style]="styleExpr">`)
|
|
||||||
1. Static value (for example, `<div class="foo">` or `<div style="color: blue">`)
|
|
||||||
1. Directive host bindings
|
|
||||||
1. Property binding (for example, `host: {'[class.foo]': 'hasFoo'}` or `host: {'[style.color]': 'color'}`)
|
|
||||||
1. Map binding (for example, `host: {'[class]': 'classExpr'}` or `host: {'[style]': 'styleExpr'}`)
|
|
||||||
1. Static value (for example, `host: {'class': 'foo'}` or `host: {'style': 'color: blue'}`)
|
|
||||||
1. Component host bindings
|
|
||||||
1. Property binding (for example, `host: {'[class.foo]': 'hasFoo'}` or `host: {'[style.color]': 'color'}`)
|
|
||||||
1. Map binding (for example, `host: {'[class]': 'classExpr'}` or `host: {'[style]': 'styleExpr'}`)
|
|
||||||
1. Static value (for example, `host: {'class': 'foo'}` or `host: {'style': 'color: blue'}`)
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
The more specific a class or style binding is, the higher its precedence.
|
|
||||||
|
|
||||||
A binding to a specific class (for example, `[class.foo]`) will take precedence over a generic `[class]` binding, and a binding to a specific style (for example, `[style.bar]`) will take precedence over a generic `[style]` binding.
|
|
||||||
|
|
||||||
<code-example path="attribute-binding/src/app/app.component.html" region="basic-specificity" header="src/app/app.component.html"></code-example>
|
|
||||||
|
|
||||||
Specificity rules also apply when it comes to bindings that originate from different sources.
|
|
||||||
It's possible for an element to have bindings in the template where it's declared, from host bindings on matched directives, and from host bindings on matched components.
|
|
||||||
|
|
||||||
Template bindings are the most specific because they apply to the element directly and exclusively, so they have the highest precedence.
|
|
||||||
|
|
||||||
Directive host bindings are considered less specific because directives can be used in multiple locations, so they have a lower precedence than template bindings.
|
|
||||||
|
|
||||||
Directives often augment component behavior, so host bindings from components have the lowest precedence.
|
|
||||||
|
|
||||||
<code-example path="attribute-binding/src/app/app.component.html" region="source-specificity" header="src/app/app.component.html"></code-example>
|
|
||||||
|
|
||||||
In addition, bindings take precedence over static attributes.
|
|
||||||
|
|
||||||
In the following case, `class` and `[class]` have similar specificity, but the `[class]` binding will take precedence because it is dynamic.
|
|
||||||
|
|
||||||
<code-example path="attribute-binding/src/app/app.component.html" region="dynamic-priority" header="src/app/app.component.html"></code-example>
|
|
||||||
|
|
||||||
{@a styling-delegation}
|
|
||||||
### Delegating to styles with lower precedence
|
|
||||||
|
|
||||||
It is possible for higher precedence styles to "delegate" to lower precedence styles using `undefined` values.
|
|
||||||
Whereas setting a style property to `null` ensures the style is removed, setting it to `undefined` will cause Angular to fall back to the next-highest precedence binding to that style.
|
|
||||||
|
|
||||||
For example, consider the following template:
|
|
||||||
|
|
||||||
<code-example path="attribute-binding/src/app/app.component.html" region="style-delegation" header="src/app/app.component.html"></code-example>
|
|
||||||
|
|
||||||
Imagine that the `dirWithHostBinding` directive and the `comp-with-host-binding` component both have a `[style.width]` host binding.
|
|
||||||
In that case, if `dirWithHostBinding` sets its binding to `undefined`, the `width` property will fall back to the value of the `comp-with-host-binding` host binding.
|
|
||||||
However, if `dirWithHostBinding` sets its binding to `null`, the `width` property will be removed entirely.
|
|
||||||
|
|
|
@ -39,7 +39,34 @@ which is the attribute, spelled with a lowercase `s`.
|
||||||
|
|
||||||
For more details, see the [MDN HTMLTableCellElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) documentation.
|
For more details, see the [MDN HTMLTableCellElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) documentation.
|
||||||
|
|
||||||
For more information about `colSpan` and `colspan`, see the [Attribute binding](guide/attribute-binding#colspan) guide.
|
{@a colspan}
|
||||||
|
|
||||||
|
#### `colspan` and `colSpan`
|
||||||
|
|
||||||
|
A common point of confusion is between the attribute, `colspan`, and the property, `colSpan`.
|
||||||
|
Notice that these two names differ by only a single letter.
|
||||||
|
|
||||||
|
If you wrote something like this:
|
||||||
|
|
||||||
|
<code-example language="html">
|
||||||
|
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
You'd get this error:
|
||||||
|
|
||||||
|
<code-example language="bash">
|
||||||
|
Template parse errors:
|
||||||
|
Can't bind to 'colspan' since it isn't a known native property
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
As the message says, the `<td>` element does not have a `colspan` property. This is true
|
||||||
|
because `colspan` is an attribute—`colSpan`, with a capital `S`, is the
|
||||||
|
corresponding property. Interpolation and property binding can set only *properties*, not attributes.
|
||||||
|
|
||||||
|
Instead, you'd use property binding and write it like this:
|
||||||
|
|
||||||
|
<code-example path="attribute-binding/src/app/app.component.html" region="colSpan" header="src/app/app.component.html"></code-example>
|
||||||
|
|
||||||
|
|
||||||
Another example is disabling a button when the component says that it `isUnchanged`:
|
Another example is disabling a button when the component says that it `isUnchanged`:
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
# Style Precedence
|
||||||
|
|
||||||
|
When there are multiple bindings to the same class name or style attribute, Angular uses a set of precedence rules to determine which classes or styles to apply to the element.
|
||||||
|
These rules specify an order for which style- and class-related bindings have priority.
|
||||||
|
This styling precedence is as follows, from the most specific with the highest priority to least specific with the lowest priorty:
|
||||||
|
|
||||||
|
1. Template bindings are the most specific because they apply to the element directly and exclusively, so they have the highest precedence.
|
||||||
|
<table width="100%">
|
||||||
|
<col width="40%"></col>
|
||||||
|
<col width="60%"></col>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Binding type</th>
|
||||||
|
<th>Example</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Property binding</td>
|
||||||
|
<td><code><div [class.foo]="hasFoo"></code><br><code><div [style.color]="color"></code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Map binding</td>
|
||||||
|
<td><code><div [class]="classExpression"></code><br><code><div [style]="styleExpression"></code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Static value</td>
|
||||||
|
<td><code><div class="foo"></code><br><code><div style="color: blue"></code></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
1. Directive host bindings are less specific because you can use directives in multiple locations, so they have a lower precedence than template bindings.
|
||||||
|
<table width="100%">
|
||||||
|
<col width="40%"></col>
|
||||||
|
<col width="60%"></col>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Binding type</th>
|
||||||
|
<th>Example</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Property binding</td>
|
||||||
|
<td><code>host: {'[class.foo]': 'hasFoo'}</code><br><code>host: {'[style.color]': 'color'}</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Map binding</td>
|
||||||
|
<td><code>host: {'[class]': 'classExpr'}</code><br><code>host: {'[style]': 'styleExpr'}</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Static value</td>
|
||||||
|
<td><code>host: {'class': 'foo'}</code><br><code>host: {'style': 'color: blue'}</code></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
1. Component host bindings have the lowest precedence.
|
||||||
|
<table width="100%">
|
||||||
|
<col width="40%"></col>
|
||||||
|
<col width="60%"></col>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Binding type</th>
|
||||||
|
<th>Example</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Property binding</td>
|
||||||
|
<td><code>host: {'[class.foo]': 'hasFoo'}</code><br><code>host: {'[style.color]': 'color'}</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Map binding</td>
|
||||||
|
<td><code>host: {'[class]': 'classExpression'}</code><br><code>host: {'[style]': 'styleExpression'}</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Static value</td>
|
||||||
|
<td><code>host: {'class': 'foo'}</code><br><code>host: {'style': 'color: blue'}</code></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
## Precedence and specificity
|
||||||
|
|
||||||
|
In the following example, binding to a specific class, as in `[class.special]`, takes precedence over a generic `[class]` binding.
|
||||||
|
Similarly, binding to a specific style, as in `[style.color]`, takes precedence over a generic `[style]` binding.
|
||||||
|
|
||||||
|
<code-example path="attribute-binding/src/app/app.component.html" region="basic-specificity" header="src/app/app.component.html"></code-example>
|
||||||
|
|
||||||
|
## Precedence and bindings from different sources
|
||||||
|
|
||||||
|
Specificity rules also apply to bindings even when they originate from different sources.
|
||||||
|
An element can have bindings that originate from its own template, from host bindings on matched directives, and from host bindings on matched components.
|
||||||
|
|
||||||
|
<code-example path="attribute-binding/src/app/app.component.html" region="source-specificity" header="src/app/app.component.html"></code-example>
|
||||||
|
|
||||||
|
## Precedence of bindings and static attributes
|
||||||
|
|
||||||
|
Bindings take precedence over static attributes because they are dynamic.
|
||||||
|
In the following case, `class` and `[class]` have similar specificity, but the `[class]` binding takes precedence.
|
||||||
|
|
||||||
|
<code-example path="attribute-binding/src/app/app.component.html" region="dynamic-priority" header="src/app/app.component.html"></code-example>
|
||||||
|
|
||||||
|
{@a styling-delegation}
|
||||||
|
|
||||||
|
## Delegating to styles with lower precedence
|
||||||
|
|
||||||
|
Higher precedence styles can defer to lower precedence styles using `undefined` values.
|
||||||
|
For example, consider the following template:
|
||||||
|
|
||||||
|
<code-example path="attribute-binding/src/app/app.component.html" region="style-delegation" header="src/app/app.component.html"></code-example>
|
||||||
|
|
||||||
|
Imagine that the `dirWithHostBinding` directive and the `comp-with-host-binding` component both have a `[style.width]` host binding.
|
||||||
|
|
||||||
|
<code-example path="attribute-binding/src/app/comp-with-host-binding.component.ts" region="hostbinding" header="src/app/comp-with-host-binding.component.ts and dirWithHostBinding.directive.ts"></code-example>
|
||||||
|
|
||||||
|
If `dirWithHostBinding` sets its binding to `undefined`, the `width` property falls back to the value of the `comp-with-host-binding` host binding.
|
||||||
|
|
||||||
|
<code-example header="dirWithHostBinding directive">
|
||||||
|
@HostBinding('style.width')
|
||||||
|
width = ''; // undefined
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
If `dirWithHostBinding` sets its binding to `null`, Angular removes the `width` property entirely.
|
||||||
|
|
||||||
|
<code-example header="dirWithHostBinding">
|
||||||
|
@HostBinding('style.width')
|
||||||
|
width = null;
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
</div>
|
Loading…
Reference in New Issue