|
| 1 | + |
| 2 | +# Binding syntax: an overview |
| 3 | + |
| 4 | +Data-binding is a mechanism for coordinating what users see, specifically |
| 5 | +with application data values. |
| 6 | +While you could push values to and pull values from HTML, |
| 7 | +the application is easier to write, read, and maintain if you turn these tasks over to a binding framework. |
| 8 | +You simply declare bindings between binding sources, target HTML elements, and let the framework do the rest. |
| 9 | + |
| 10 | +<div class="alert is-helpful"> |
| 11 | + |
| 12 | +See the <live-example></live-example> for a working example containing the code snippets in this guide. |
| 13 | + |
| 14 | +</div> |
| 15 | + |
| 16 | +Angular provides many kinds of data-binding. Binding types can be grouped into three categories distinguished by the direction of data flow: |
| 17 | + |
| 18 | +* From the _source-to-view_ |
| 19 | +* From _view-to-source_ |
| 20 | +* Two-way sequence: _view-to-source-to-view_ |
| 21 | + |
| 22 | +<style> |
| 23 | + td, th {vertical-align: top} |
| 24 | +</style> |
| 25 | + |
| 26 | +<table width="100%"> |
| 27 | + <col width="30%"> |
| 28 | + </col> |
| 29 | + <col width="50%"> |
| 30 | + </col> |
| 31 | + <col width="20%"> |
| 32 | + </col> |
| 33 | + <tr> |
| 34 | + <th> |
| 35 | + Type |
| 36 | + </th> |
| 37 | + <th> |
| 38 | + Syntax |
| 39 | + </th> |
| 40 | + <th> |
| 41 | + Category |
| 42 | + </th> |
| 43 | + |
| 44 | + </tr> |
| 45 | + <tr> |
| 46 | + <td> |
| 47 | + Interpolation<br> |
| 48 | + Property<br> |
| 49 | + Attribute<br> |
| 50 | + Class<br> |
| 51 | + Style |
| 52 | + </td> |
| 53 | + <td> |
| 54 | + |
| 55 | + <code-example> |
| 56 | + {{expression}} |
| 57 | + [target]="expression" |
| 58 | + bind-target="expression" |
| 59 | + </code-example> |
| 60 | + |
| 61 | + </td> |
| 62 | + |
| 63 | + <td> |
| 64 | + One-way<br>from data source<br>to view target |
| 65 | + </td> |
| 66 | + <tr> |
| 67 | + <td> |
| 68 | + Event |
| 69 | + </td> |
| 70 | + <td> |
| 71 | + <code-example> |
| 72 | + (target)="statement" |
| 73 | + on-target="statement" |
| 74 | + </code-example> |
| 75 | + </td> |
| 76 | + |
| 77 | + <td> |
| 78 | + One-way<br>from view target<br>to data source |
| 79 | + </td> |
| 80 | + </tr> |
| 81 | + <tr> |
| 82 | + <td> |
| 83 | + Two-way |
| 84 | + </td> |
| 85 | + <td> |
| 86 | + <code-example> |
| 87 | + [(target)]="expression" |
| 88 | + bindon-target="expression" |
| 89 | + </code-example> |
| 90 | + </td> |
| 91 | + <td> |
| 92 | + Two-way |
| 93 | + </td> |
| 94 | + </tr> |
| 95 | + </tr> |
| 96 | +</table> |
| 97 | + |
| 98 | +Binding types other than interpolation have a **target name** to the left of the equal sign, either surrounded by punctuation, `[]` or `()`, |
| 99 | +or preceded by a prefix: `bind-`, `on-`, `bindon-`. |
| 100 | + |
| 101 | +The *target* of a binding is the property or event inside the binding punctuation: `[]`, `()` or `[()]`. |
| 102 | + |
| 103 | +Every public member of a **source** directive is automatically available for binding. |
| 104 | +You don't have to do anything special to access a directive member in a template expression or statement. |
| 105 | + |
| 106 | + |
| 107 | +### Data-binding and HTML |
| 108 | + |
| 109 | +In the normal course of HTML development, you create a visual structure with HTML elements, and |
| 110 | +you modify those elements by setting element attributes with string constants. |
| 111 | + |
| 112 | +```html |
| 113 | +<div class="special">Plain old HTML</div> |
| 114 | +<img src="images/item.png"> |
| 115 | +<button disabled>Save</button> |
| 116 | +``` |
| 117 | + |
| 118 | +With data-binding, you can control things like the state of a button: |
| 119 | + |
| 120 | +<code-example path="binding-syntax/src/app/app.component.html" region="disabled-button" header="src/app/app.component.html"></code-example> |
| 121 | + |
| 122 | +Notice that the binding is to the `disabled` property of the button's DOM element, |
| 123 | +**not** the attribute. This applies to data-binding in general. Data-binding works with *properties* of DOM elements, components, and directives, not HTML *attributes*. |
| 124 | + |
| 125 | +{@a html-attribute-vs-dom-property} |
| 126 | + |
| 127 | +### HTML attribute vs. DOM property |
| 128 | + |
| 129 | +The distinction between an HTML attribute and a DOM property is key to understanding |
| 130 | +how Angular binding works. **Attributes are defined by HTML. Properties are accessed from DOM (Document Object Model) nodes.** |
| 131 | + |
| 132 | +* A few HTML attributes have 1:1 mapping to properties; for example, `id`. |
| 133 | + |
| 134 | +* Some HTML attributes don't have corresponding properties; for example, `aria-*`. |
| 135 | + |
| 136 | +* Some DOM properties don't have corresponding attributes; for example, `textContent`. |
| 137 | + |
| 138 | +It is important to remember that *HTML attribute* and the *DOM property* are different things, even when they have the same name. |
| 139 | +In Angular, the only role of HTML attributes is to initialize element and directive state. |
| 140 | + |
| 141 | +**Template binding works with *properties* and *events*, not *attributes*.** |
| 142 | + |
| 143 | +When you write a data-binding, you're dealing exclusively with the *DOM properties* and *events* of the target object. |
| 144 | + |
| 145 | +<div class="alert is-helpful"> |
| 146 | + |
| 147 | +This general rule can help you build a mental model of attributes and DOM properties: |
| 148 | +**Attributes initialize DOM properties and then they are done. |
| 149 | +Property values can change; attribute values can't.** |
| 150 | + |
| 151 | +There is one exception to this rule. |
| 152 | +Attributes can be changed by `setAttribute()`, which re-initializes corresponding DOM properties. |
| 153 | + |
| 154 | +</div> |
| 155 | + |
| 156 | +For more information, see the [MDN Interfaces documentation](https://developer.mozilla.org/en-US/docs/Web/API#Interfaces) which has API docs for all the standard DOM elements and their properties. |
| 157 | +Comparing the [`<td>` attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td) attributes to the [`<td>` properties](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) provides a helpful example for differentiation. |
| 158 | +In particular, you can navigate from the attributes page to the properties via "DOM interface" link, and navigate the inheritance hierarchy up to `HTMLTableCellElement`. |
| 159 | + |
| 160 | + |
| 161 | +#### Example 1: an `<input>` |
| 162 | + |
| 163 | +When the browser renders `<input type="text" value="Sarah">`, it creates a |
| 164 | +corresponding DOM node with a `value` property initialized to "Sarah". |
| 165 | + |
| 166 | +```html |
| 167 | +<input type="text" value="Sarah"> |
| 168 | +``` |
| 169 | + |
| 170 | +When the user enters "Sally" into the `<input>`, the DOM element `value` *property* becomes "Sally". |
| 171 | +However, if you look at the HTML attribute `value` using `input.getAttribute('value')`, you can see that the *attribute* remains unchanged—it returns "Sarah". |
| 172 | + |
| 173 | +The HTML attribute `value` specifies the *initial* value; the DOM `value` property is the *current* value. |
| 174 | + |
| 175 | +To see attributes versus DOM properties in a functioning app, see the <live-example name="binding-syntax"></live-example> especially for binding syntax. |
| 176 | + |
| 177 | +#### Example 2: a disabled button |
| 178 | + |
| 179 | +The `disabled` attribute is another example. A button's `disabled` |
| 180 | +*property* is `false` by default so the button is enabled. |
| 181 | + |
| 182 | +When you add the `disabled` *attribute*, its presence alone |
| 183 | +initializes the button's `disabled` *property* to `true` |
| 184 | +so the button is disabled. |
| 185 | + |
| 186 | +```html |
| 187 | +<button disabled>Test Button</button> |
| 188 | +``` |
| 189 | + |
| 190 | +Adding and removing the `disabled` *attribute* disables and enables the button. |
| 191 | +However, the value of the *attribute* is irrelevant, |
| 192 | +which is why you cannot enable a button by writing `<button disabled="false">Still Disabled</button>`. |
| 193 | + |
| 194 | +To control the state of the button, set the `disabled` *property*, |
| 195 | + |
| 196 | +<div class="alert is-helpful"> |
| 197 | + |
| 198 | +Though you could technically set the `[attr.disabled]` attribute binding, the values are different in that the property binding requires to a boolean value, while its corresponding attribute binding relies on whether the value is `null` or not. Consider the following: |
| 199 | + |
| 200 | +```html |
| 201 | +<input [disabled]="condition ? true : false"> |
| 202 | +<input [attr.disabled]="condition ? 'disabled' : null"> |
| 203 | +``` |
| 204 | + |
| 205 | +Generally, use property binding over attribute binding as it is more intuitive (being a boolean value), has a shorter syntax, and is more performant. |
| 206 | + |
| 207 | +</div> |
| 208 | + |
| 209 | + |
| 210 | +To see the `disabled` button example in a functioning app, see the <live-example name="binding-syntax"></live-example> especially for binding syntax. This example shows you how to toggle the disabled property from the component. |
| 211 | + |
| 212 | +## Binding types and targets |
| 213 | + |
| 214 | +The **target of a data-binding** is something in the DOM. |
| 215 | +Depending on the binding type, the target can be a property (element, component, or directive), |
| 216 | +an event (element, component, or directive), or sometimes an attribute name. |
| 217 | +The following table summarizes the targets for the different binding types. |
| 218 | + |
| 219 | +<style> |
| 220 | + td, th {vertical-align: top} |
| 221 | +</style> |
| 222 | + |
| 223 | +<table width="100%"> |
| 224 | + <col width="10%"> |
| 225 | + </col> |
| 226 | + <col width="15%"> |
| 227 | + </col> |
| 228 | + <col width="75%"> |
| 229 | + </col> |
| 230 | + <tr> |
| 231 | + <th> |
| 232 | + Type |
| 233 | + </th> |
| 234 | + <th> |
| 235 | + Target |
| 236 | + </th> |
| 237 | + <th> |
| 238 | + Examples |
| 239 | + </th> |
| 240 | + </tr> |
| 241 | + <tr> |
| 242 | + <td> |
| 243 | + Property |
| 244 | + </td> |
| 245 | + <td> |
| 246 | + Element property<br> |
| 247 | + Component property<br> |
| 248 | + Directive property |
| 249 | + </td> |
| 250 | + <td> |
| 251 | + <code>src</code>, <code>hero</code>, and <code>ngClass</code> in the following: |
| 252 | + <code-example path="template-syntax/src/app/app.component.html" region="property-binding-syntax-1"></code-example> |
| 253 | + <!-- For more information, see [Property Binding](guide/property-binding). --> |
| 254 | + </td> |
| 255 | + </tr> |
| 256 | + <tr> |
| 257 | + <td> |
| 258 | + Event |
| 259 | + </td> |
| 260 | + <td> |
| 261 | + Element event<br> |
| 262 | + Component event<br> |
| 263 | + Directive event |
| 264 | + </td> |
| 265 | + <td> |
| 266 | + <code>click</code>, <code>deleteRequest</code>, and <code>myClick</code> in the following: |
| 267 | + <code-example path="template-syntax/src/app/app.component.html" region="event-binding-syntax-1"></code-example> |
| 268 | + <!-- KW--Why don't these links work in the table? --> |
| 269 | + <!-- <div>For more information, see [Event Binding](guide/event-binding).</div> --> |
| 270 | + </td> |
| 271 | + </tr> |
| 272 | + <tr> |
| 273 | + <td> |
| 274 | + Two-way |
| 275 | + </td> |
| 276 | + <td> |
| 277 | + Event and property |
| 278 | + </td> |
| 279 | + <td> |
| 280 | + <code-example path="template-syntax/src/app/app.component.html" region="2-way-binding-syntax-1"></code-example> |
| 281 | + </td> |
| 282 | + </tr> |
| 283 | + <tr> |
| 284 | + <td> |
| 285 | + Attribute |
| 286 | + </td> |
| 287 | + <td> |
| 288 | + Attribute |
| 289 | + (the exception) |
| 290 | + </td> |
| 291 | + <td> |
| 292 | + <code-example path="template-syntax/src/app/app.component.html" region="attribute-binding-syntax-1"></code-example> |
| 293 | + </td> |
| 294 | + </tr> |
| 295 | + <tr> |
| 296 | + <td> |
| 297 | + Class |
| 298 | + </td> |
| 299 | + <td> |
| 300 | + <code>class</code> property |
| 301 | + </td> |
| 302 | + <td> |
| 303 | + <code-example path="template-syntax/src/app/app.component.html" region="class-binding-syntax-1"></code-example> |
| 304 | + </td> |
| 305 | + </tr> |
| 306 | + <tr> |
| 307 | + <td> |
| 308 | + Style |
| 309 | + </td> |
| 310 | + <td> |
| 311 | + <code>style</code> property |
| 312 | + </td> |
| 313 | + <td> |
| 314 | + <code-example path="template-syntax/src/app/app.component.html" region="style-binding-syntax-1"></code-example> |
| 315 | + </td> |
| 316 | + </tr> |
| 317 | +</table> |
| 318 | + |
0 commit comments