docs: edit two-way binding doc (#38952)
This commit edits copy and doc regions to clarify concepts. PR Close #38952
This commit is contained in:
parent
b015d3e950
commit
a87236292e
|
@ -1,7 +1,9 @@
|
||||||
<h1 id="two-way">Two-way Binding</h1>
|
<h1 id="two-way">Two-way Binding</h1>
|
||||||
<div id="two-way-1">
|
<div id="two-way-1">
|
||||||
<!-- #docregion two-way-1 -->
|
<!-- #docregion two-way-1 -->
|
||||||
|
<!-- #docregion two-way-syntax -->
|
||||||
<app-sizer [(size)]="fontSizePx"></app-sizer>
|
<app-sizer [(size)]="fontSizePx"></app-sizer>
|
||||||
|
<!-- #enddocregion two-way-syntax-->
|
||||||
<div [style.font-size.px]="fontSizePx">Resizable Text</div>
|
<div [style.font-size.px]="fontSizePx">Resizable Text</div>
|
||||||
<!-- #enddocregion two-way-1 -->
|
<!-- #enddocregion two-way-1 -->
|
||||||
<label>FontSize (px): <input [(ngModel)]="fontSizePx"></label>
|
<label>FontSize (px): <input [(ngModel)]="fontSizePx"></label>
|
||||||
|
|
|
@ -5,9 +5,9 @@ import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||||
templateUrl: './sizer.component.html',
|
templateUrl: './sizer.component.html',
|
||||||
styleUrls: ['./sizer.component.css']
|
styleUrls: ['./sizer.component.css']
|
||||||
})
|
})
|
||||||
|
// #docregion sizer-component
|
||||||
export class SizerComponent {
|
export class SizerComponent {
|
||||||
|
|
||||||
|
|
||||||
@Input() size: number | string;
|
@Input() size: number | string;
|
||||||
@Output() sizeChange = new EventEmitter<number>();
|
@Output() sizeChange = new EventEmitter<number>();
|
||||||
|
|
||||||
|
@ -18,5 +18,5 @@ export class SizerComponent {
|
||||||
this.size = Math.min(40, Math.max(8, +this.size + delta));
|
this.size = Math.min(40, Math.max(8, +this.size + delta));
|
||||||
this.sizeChange.emit(this.size);
|
this.sizeChange.emit(this.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// #enddocregion sizer-component
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Two-way binding `[(...)]`
|
# Two-way binding
|
||||||
|
|
||||||
Two-way binding gives your app a way to share data between a component class and
|
Two-way binding gives components in your application a way to share data.
|
||||||
its template.
|
Use two-way binding binding to listen for events and update values simultaneously between parent and child components.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
@ -9,68 +9,73 @@ See the <live-example></live-example> for a working example containing the code
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## Basics of two-way binding
|
## Prerequisites
|
||||||
|
|
||||||
Two-way binding does two things:
|
To get the most out of two-way binding, you should have a basic understanding of the following concepts:
|
||||||
|
|
||||||
1. Sets a specific element property.
|
* [Property binding](guide/property-binding)
|
||||||
1. Listens for an element change event.
|
* [Event binding](guide/event-binding)
|
||||||
|
* [Inputs and Outputs](guide/inputs-outputs)
|
||||||
|
|
||||||
Angular offers a special _two-way data binding_ syntax for this purpose, `[()]`.
|
<hr>
|
||||||
The `[()]` syntax combines the brackets
|
|
||||||
of property binding, `[]`, with the parentheses of event binding, `()`.
|
|
||||||
|
|
||||||
<div class="callout is-important">
|
Two-way binding combines property binding with event binding:
|
||||||
|
|
||||||
<header>
|
* [Property binding](guide/property-binding) sets a specific element property.
|
||||||
[( )] = banana in a box
|
* [Event binding](guide/event-binding) listens for an element change event.
|
||||||
</header>
|
|
||||||
|
|
||||||
Visualize a *banana in a box* to remember that the parentheses go _inside_ the brackets.
|
## Adding two-way data binding
|
||||||
|
|
||||||
</div>
|
Angular's two-way binding syntax is a combination of square brackets and parentheses, `[()]`.
|
||||||
|
The `[()]` syntax combines the brackets of property binding, `[]`, with the parentheses of event binding, `()`, as follows.
|
||||||
|
|
||||||
The `[()]` syntax is easy to demonstrate when the element has a settable
|
<code-example path="two-way-binding/src/app/app.component.html" header="src/app/app.component.html" region="two-way-syntax"></code-example>
|
||||||
property called `x` and a corresponding event named `xChange`.
|
|
||||||
Here's a `SizerComponent` that fits this pattern.
|
|
||||||
It has a `size` value property and a companion `sizeChange` event:
|
|
||||||
|
|
||||||
<code-example path="two-way-binding/src/app/sizer/sizer.component.ts" header="src/app/sizer.component.ts"></code-example>
|
## How two-way binding works
|
||||||
|
|
||||||
|
For two-way data binding to work, the `@Output()` property must use the pattern, `inputChange`, where `input` is the name of the `@Input()` property.
|
||||||
|
For example, if the `@Input()` property is `size`, the `@Output()` property must be `sizeChange`.
|
||||||
|
|
||||||
|
The following `sizerComponent` has a `size` value property and a `sizeChange` event.
|
||||||
|
The `size` property is an `@Input()`, so data can flow into the `sizerComponent`.
|
||||||
|
The `sizeChange` event is an `@Output()`, which allows data to flow out of the `sizerComponent` to the parent component.
|
||||||
|
|
||||||
|
Next, there are two methods, `dec()` to decrease the font size and `inc()` to increase the font size.
|
||||||
|
These two methods use `resize()` to change the value of the `size` property within min/max value constraints, and to emit an event that conveys the new `size` value.
|
||||||
|
|
||||||
|
<code-example path="two-way-binding/src/app/sizer/sizer.component.ts" region="sizer-component" header="src/app/sizer.component.ts"></code-example>
|
||||||
|
|
||||||
|
The `sizerComponent` template has two buttons that each bind the click event to the `inc()` and `dec()` methods.
|
||||||
|
When the user clicks one of the buttons, the `sizerComponent` calls the corresponding method.
|
||||||
|
Both methods, `inc()` and `dec()`, call the `resize()` method with a `+1` or `-1`, which in turn raises the `sizeChange` event with the new size value.
|
||||||
|
|
||||||
<code-example path="two-way-binding/src/app/sizer/sizer.component.html" header="src/app/sizer.component.html"></code-example>
|
<code-example path="two-way-binding/src/app/sizer/sizer.component.html" header="src/app/sizer.component.html"></code-example>
|
||||||
|
|
||||||
The initial `size` is an input value from a property binding.
|
|
||||||
Clicking the buttons increases or decreases the `size`, within
|
|
||||||
min/max value constraints,
|
|
||||||
and then raises, or emits, the `sizeChange` event with the adjusted size.
|
|
||||||
|
|
||||||
Here's an example in which the `AppComponent.fontSizePx` is two-way bound to the `SizerComponent`:
|
In the `AppComponent` template, `fontSizePx` is two-way bound to the `SizerComponent`.
|
||||||
|
|
||||||
<code-example path="two-way-binding/src/app/app.component.html" header="src/app/app.component.html (two-way-1)" region="two-way-1"></code-example>
|
<code-example path="two-way-binding/src/app/app.component.html" header="src/app/app.component.html" region="two-way-1"></code-example>
|
||||||
|
|
||||||
The `AppComponent.fontSizePx` establishes the initial `SizerComponent.size` value.
|
In the `AppComponent`, `fontSizePx` establishes the initial `SizerComponent.size` value by setting the value to `16`.
|
||||||
|
|
||||||
<code-example path="two-way-binding/src/app/app.component.ts" header="src/app/app.component.ts" region="font-size"></code-example>
|
<code-example path="two-way-binding/src/app/app.component.ts" header="src/app/app.component.ts" region="font-size"></code-example>
|
||||||
|
|
||||||
Clicking the buttons updates the `AppComponent.fontSizePx` via the two-way binding.
|
Clicking the buttons updates the `AppComponent.fontSizePx`.
|
||||||
The revised `AppComponent.fontSizePx` value flows through to the _style_ binding,
|
The revised `AppComponent.fontSizePx` value updates the style binding, which makes the displayed text bigger or smaller.
|
||||||
making the displayed text bigger or smaller.
|
|
||||||
|
|
||||||
The two-way binding syntax is really just syntactic sugar for a _property_ binding and an _event_ binding.
|
The two-way binding syntax is shorthand for a combination of property binding and event binding.
|
||||||
Angular desugars the `SizerComponent` binding into this:
|
The `SizerComponent` binding as separate property binding and event binding is as follows.
|
||||||
|
|
||||||
<code-example path="two-way-binding/src/app/app.component.html" header="src/app/app.component.html (two-way-2)" region="two-way-2"></code-example>
|
<code-example path="two-way-binding/src/app/app.component.html" header="src/app/app.component.html (expanded)" region="two-way-2"></code-example>
|
||||||
|
|
||||||
The `$event` variable contains the payload of the `SizerComponent.sizeChange` event.
|
The `$event` variable contains the data of the `SizerComponent.sizeChange` event.
|
||||||
Angular assigns the `$event` value to the `AppComponent.fontSizePx` when the user clicks the buttons.
|
Angular assigns the `$event` value to the `AppComponent.fontSizePx` when the user clicks the buttons.
|
||||||
|
|
||||||
## Two-way binding in forms
|
<div class="callout is-helpful">
|
||||||
|
|
||||||
The two-way binding syntax is a great convenience compared to
|
<header>Two-way binding in forms</header>
|
||||||
separate property and event bindings. It would be convenient to
|
|
||||||
use two-way binding with HTML form elements like `<input>` and
|
|
||||||
`<select>`. However, no native HTML element follows the `x`
|
|
||||||
value and `xChange` event pattern.
|
|
||||||
|
|
||||||
For more on how to use two-way binding in forms, see
|
Because no native HTML element follows the `x` value and `xChange` event pattern, two-way binding with form elements requires `NgModel`.
|
||||||
Angular [NgModel](guide/built-in-directives#ngModel).
|
For more information on how to use two-way binding in forms, see Angular [NgModel](guide/built-in-directives#ngModel).
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue