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/examples/structural-directives/**',
|
||||
'aio/content/guide/svg-in-templates.md',
|
||||
'aio/content/guide/style-precedence.md',
|
||||
'aio/content/images/guide/structural-directives/**',
|
||||
'aio/content/guide/template-statements.md',
|
||||
'aio/content/guide/user-input.md',
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
<h2>Attribute binding</h2>
|
||||
<!-- #docregion attrib-binding-colspan -->
|
||||
<table border=1>
|
||||
<!-- #docregion colspan -->
|
||||
<!-- expression calculates colspan=2 -->
|
||||
<tr><td [attr.colspan]="1 + 1">One-Two</td></tr>
|
||||
<!-- #enddocregion colspan -->
|
||||
|
||||
<!-- ERROR: There is no `colspan` property to set!
|
||||
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
|
||||
|
@ -32,31 +34,31 @@
|
|||
<!-- #docregion basic-specificity -->
|
||||
<h3>Basic specificity</h3>
|
||||
|
||||
<!-- The `class.special` binding will override any value for the `special` class in `classExpr`. -->
|
||||
<div [class.special]="isSpecial" [class]="classExpr">Some text.</div>
|
||||
<!-- The `class.special` binding overrides any value for the `special` class in `classExpression`. -->
|
||||
<div [class.special]="isSpecial" [class]="classExpression">Some text.</div>
|
||||
|
||||
<!-- The `style.color` binding will override any value for the `color` property in `styleExpr`. -->
|
||||
<div [style.color]="color" [style]="styleExpr">Some text.</div>
|
||||
<!-- The `style.color` binding overrides any value for the `color` property in `styleExpression`. -->
|
||||
<div [style.color]="color" [style]="styleExpression">Some text.</div>
|
||||
<!-- #enddocregion basic-specificity -->
|
||||
|
||||
<!-- #docregion source-specificity -->
|
||||
<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>
|
||||
|
||||
<!-- 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>
|
||||
<!-- #enddocregion source-specificity -->
|
||||
|
||||
<!-- #docregion dynamic-priority -->
|
||||
<h3>Dynamic vs static</h3>
|
||||
|
||||
<!-- If `classExpr` has a value for the `special` class, this value will override the `class="special"` below -->
|
||||
<div class="special" [class]="classExpr">Some text.</div>
|
||||
<!-- If `classExpression` has a value for the `special` class, this value overrides the `class="special"` below -->
|
||||
<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 -->
|
||||
<div style="color: blue" [style]="styleExpr">Some text.</div>
|
||||
<!-- If `styleExpression` has a value for the `color` property, this value overrides the `style="color: blue"` below -->
|
||||
<div style="color: blue" [style]="styleExpression">Some text.</div>
|
||||
|
||||
<!-- #enddocregion dynamic-priority -->
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ export class AppComponent {
|
|||
actionName = 'Go for it';
|
||||
isSpecial = true;
|
||||
canSave = true;
|
||||
classExpr = 'special clearance';
|
||||
styleExpr = 'color: red';
|
||||
classExpression = 'special clearance';
|
||||
styleExpression = 'color: red';
|
||||
color = 'blue';
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@ export class CompWithHostBindingComponent {
|
|||
@HostBinding('style.color')
|
||||
color = 'green';
|
||||
|
||||
// #docregion hostbinding
|
||||
@HostBinding('style.width')
|
||||
width = '200px';
|
||||
// #enddocregion hostbinding
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# 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">
|
||||
|
||||
|
@ -8,23 +9,36 @@ See the <live-example></live-example> for a working example containing the code
|
|||
|
||||
</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
|
||||
[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.
|
||||
## Syntax
|
||||
|
||||
Attribute binding syntax resembles property binding, but
|
||||
instead of an element property between brackets, start with the prefix `attr`,
|
||||
followed by a dot (`.`), and the name of the attribute.
|
||||
You then set the attribute value, using an expression that resolves to a string,
|
||||
or remove the attribute when the expression resolves to `null`.
|
||||
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.
|
||||
Then, you set the attribute value with an expression that resolves to a string.
|
||||
|
||||
<code-example language="html">
|
||||
|
||||
<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
|
||||
is to set ARIA attributes, as in this example:
|
||||
|
@ -33,32 +47,30 @@ is to set ARIA attributes, as in this example:
|
|||
|
||||
{@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">
|
||||
|
||||
#### `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.
|
||||
|
||||
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>
|
||||
`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".
|
||||
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).
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -66,28 +78,32 @@ Instead, you'd use property binding and write it like this:
|
|||
|
||||
{@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
|
||||
<!-- standard class attribute setting -->
|
||||
<div class="foo bar">Some text</div>
|
||||
```
|
||||
### Binding to a single CSS `class`
|
||||
|
||||
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"`).
|
||||
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)).
|
||||
### Binding to multiple CSS classes
|
||||
|
||||
To create a binding to multiple classes, use a generic `[class]` binding without the dot (for example, `[class]="classExpr"`).
|
||||
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.
|
||||
With object format, Angular will add a class only if its associated value is truthy.
|
||||
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 an object with class names as the keys and truthy or falsy expressions as the values.
|
||||
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.
|
||||
Updating the property without changing object identity will have no effect.
|
||||
<div class="alert is-important">
|
||||
|
||||
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>
|
||||
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>
|
||||
<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>true</code>, <code>false</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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>"my-class-1 my-class-2 my-class-3"</code></td>
|
||||
</tr>
|
||||
|
@ -138,44 +154,44 @@ If there are multiple bindings to the same class name, conflicts are resolved us
|
|||
</tr>
|
||||
</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/>
|
||||
|
||||
## 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
|
||||
<!-- standard style attribute setting -->
|
||||
<div style="color: blue">Some text</div>
|
||||
```
|
||||
You can use style binding to set styles dynamically.
|
||||
|
||||
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"`).
|
||||
The property will be set to the value of the bound expression, which is normally a string.
|
||||
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"`.
|
||||
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.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Note that a _style property_ name can be written in either
|
||||
[dash-case](guide/glossary#dash-case), as shown above, or
|
||||
[camelCase](guide/glossary#camelcase), such as `fontSize`.
|
||||
You can write a style property name in either [dash-case](guide/glossary#dash-case), or
|
||||
[camelCase](guide/glossary#camelcase).
|
||||
|
||||
</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"`).
|
||||
The expression attached to the `[style]` binding is most often a string list of styles like `"width: 100px; height: 100px;"`.
|
||||
### Binding to multiple styles
|
||||
|
||||
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'}`.
|
||||
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.
|
||||
Updating the property without changing object identity will have no effect.
|
||||
To toggle multiple styles, bind to the `[style]` attribute—for example, `[style]="styleExpression"`).
|
||||
The expression is often a string list of styles such as `"width: 100px; height: 100px;"`.
|
||||
|
||||
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>
|
||||
td, th {vertical-align: top}
|
||||
|
@ -219,7 +235,7 @@ If there are multiple bindings to the same style property, conflicts are resolve
|
|||
</tr>
|
||||
<tr>
|
||||
<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>"width: 100px; height: 100px"</code></td>
|
||||
</tr>
|
||||
|
@ -232,72 +248,3 @@ If there are multiple bindings to the same style property, conflicts are resolve
|
|||
<td><code>['width', '100px']</code></td>
|
||||
</tr>
|
||||
</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 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`:
|
||||
|
||||
|
|
|
@ -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