Skip to content

Commit 4f6277b

Browse files
committed
docs(template-syntax): refresh _cache
1 parent 14db838 commit 4f6277b

File tree

1 file changed

+106
-64
lines changed

1 file changed

+106
-64
lines changed

public/docs/ts/_cache/guide/template-syntax.jade

+106-64
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ block includes
2121
* [Property binding](#property-binding)
2222
* [Attribute, class, and style bindings](#other-bindings)
2323
* [Event binding](#event-binding)
24+
* [Two-way data binding](#two-way)
2425
* [Two-way data binding with `NgModel`](#ngModel)
2526
* [Built-in directives](#directives)
2627
* [NgClass](#ngClass)
@@ -44,7 +45,7 @@ block includes
4445
HTML is the language of the Angular template. Our [QuickStart](../quickstart.html) application has a template that is pure HTML:
4546

4647
code-example(language="html" escape="html").
47-
<h1>My First Angular 2 App</h1>
48+
<h1>My First Angular App</h1>
4849

4950
:marked
5051
Almost all HTML syntax is valid template syntax. The `<script>` element is a notable exception; it is forbidden, eliminating the risk of script injection attacks. (In practice, `<script>` is simply ignored.)
@@ -387,7 +388,7 @@ table
387388
.callout.is-helpful
388389
header A world without attributes
389390
:marked
390-
In the world of Angular 2, the only role of attributes is to initialize element and directive state.
391+
In the world of Angular, the only role of attributes is to initialize element and directive state.
391392
When we data bind, we're dealing exclusively with element and directive properties and events.
392393
Attributes effectively disappear.
393394
:marked
@@ -489,8 +490,8 @@ table
489490
If we must read a target element property or call one of its methods,
490491
we'll need a different technique.
491492
See the API reference for
492-
[viewChild](../api/core/index/ViewChild-var.html) and
493-
[contentChild](../api/core/index/ContentChild-var.html).
493+
[viewChild](../api/core/index/ViewChild-decorator.html) and
494+
[contentChild](../api/core/index/ContentChild-decorator.html).
494495

495496
:marked
496497
### Binding target
@@ -711,12 +712,12 @@ block style-property-name-dart-diff
711712
712713
.l-main-section
713714
:marked
714-
## Event Binding
715-
The bindings we’ve met so far flow data in one direction: *from the component to an element*.
715+
## Event binding
716+
The bindings we’ve met so far flow data in one direction: **from a component to an element**.
716717

717718
Users don’t just stare at the screen. They enter text into input boxes. They pick items from lists.
718719
They click buttons. Such user actions may result in a flow of data in the opposite direction:
719-
*from an element to the component*.
720+
**from an element to a component**.
720721

721722
The only way to know about a user action is to listen for certain events such as
722723
keystrokes, mouse movements, clicks, and touches.
@@ -728,12 +729,12 @@ block style-property-name-dart-diff
728729
the component's `onSave()` method whenever a click occurs:
729730
+makeExample('template-syntax/ts/app/app.component.html', 'event-binding-1')(format=".")
730731
:marked
731-
### Target Event
732-
A **name between enclosing parentheses** &mdash; for example, `(click)` &mdash;
732+
### Target event
733+
A **name between parentheses** &mdash; for example, `(click)` &mdash;
733734
identifies the target event. In the following example, the target is the button’s click event.
734735
+makeExample('template-syntax/ts/app/app.component.html', 'event-binding-1')(format=".")
735736
:marked
736-
Some people prefer the `on-` prefix alternative, known as the *canonical form*:
737+
Some people prefer the `on-` prefix alternative, known as the **canonical form**:
737738
+makeExample('template-syntax/ts/app/app.component.html', 'event-binding-2')(format=".")
738739
:marked
739740
Element events may be the more common targets, but Angular looks first to see if the name matches an event property
@@ -742,47 +743,46 @@ block style-property-name-dart-diff
742743

743744
.l-sub-section
744745
:marked
745-
The `myClick` directive is further described below in the section
746-
on [Aliasing input/output properties](#aliasing-io).
746+
The `myClick` directive is further described in the section
747+
on [aliasing input/output properties](#aliasing-io).
747748

748749
:marked
749-
If the name fails to match an element event or an output property of a known directive,
750+
If the name fails to match element event or output property of a known directive,
750751
Angular reports an “unknown directive” error.
751752

752753
### *$event* and event handling statements
753754
In an event binding, Angular sets up an event handler for the target event.
754755

755756
When the event is raised, the handler executes the template statement.
756-
The template statement typically involves a receiver that wants to do something
757-
in response to the event, such as take a value from the HTML control and store it
758-
in a model.
757+
The template statement typically involves a receiver, which performs an action
758+
in response to the event, such as storing a value from the HTML control
759+
into a model.
759760

760761
The binding conveys information about the event, including data values, through
761762
an **event object named `$event`**.
762763

763-
The shape of the event object is determined by the target event itself.
764-
If the target event is a native DOM element event, the `$event` is a
764+
The shape of the event object is determined by the target event.
765+
If the target event is a native DOM element event, then `$event` is a
765766
[DOM event object]( https://developer.mozilla.org/en-US/docs/Web/Events),
766767
with properties such as `target` and `target.value`.
767768

768769
Consider this example:
769770
+makeExample('template-syntax/ts/app/app.component.html', 'without-NgModel')(format=".")
770771
:marked
771-
We’re binding the input box `value` to a `firstName` property, and we’re listening for changes by binding to the input boxs `input` event.
772+
This code sets the input box `value` property by binding to the `firstName` property. To listen for changes to the value, the code binds to the input box's `input` event.
772773
When the user makes changes, the `input` event is raised, and the binding executes the statement within a context that includes the DOM event object, `$event`.
773774

774-
To update the `firstName` property, we must get the changed text by following
775-
the path `$event.target.value`.
775+
To update the `firstName` property, the changed text is retrieved by following the path `$event.target.value`.
776776

777-
If the event belongs to a directive (remember: components are directives), `$event` has whatever shape the directive chose to produce.
777+
If the event belongs to a directive (recall that components are directives), `$event` has whatever shape the directive decides to produce.
778778

779779
<a id="eventemitter"></a>
780780
<a id="custom-event"></a>
781781
### Custom Events with EventEmitter
782782

783783
Directives typically raise custom events with an Angular [EventEmitter](../api/core/index/EventEmitter-class.html).
784-
A directive creates an `EventEmitter` and exposes it as a property.
785-
The directive calls `EventEmitter.emit(payload)` to fire an event, passing in a message payload that can be anything.
784+
The directive creates an `EventEmitter` and exposes it as a property.
785+
The directive calls `EventEmitter.emit(payload)` to fire an event, passing in a message payload, which can be anything.
786786
Parent directives listen for the event by binding to this property and accessing the payload through the `$event` object.
787787

788788
Consider a `HeroDetailComponent` that presents hero information and responds to user actions.
@@ -797,8 +797,8 @@ block style-property-name-dart-diff
797797

798798
:marked
799799
The component defines a `deleteRequest` property that returns an `EventEmitter`.
800-
When the user clicks *delete*, the component invokes the `delete()` method
801-
which tells the `EventEmitter` to emit a `Hero` object.
800+
When the user clicks *delete*, the component invokes the `delete()` method,
801+
telling the `EventEmitter` to emit a `Hero` object.
802802

803803
Now imagine a hosting parent component that binds to the `HeroDetailComponent`'s `deleteRequest` event.
804804

@@ -810,12 +810,11 @@ block style-property-name-dart-diff
810810

811811
### Template statements have side effects
812812
The `deleteHero` method has a side effect: it deletes a hero.
813-
Template statement side effects are not just OK, they are expected.
813+
Template statement side effects are not just OK, but expected.
814814

815815
Deleting the hero updates the model, perhaps triggering other changes
816816
including queries and saves to a remote server.
817817
These changes percolate through the system and are ultimately displayed in this and other views.
818-
It's all good.
819818

820819
//
821820
:marked
@@ -843,19 +842,64 @@ block style-property-name-dart-diff
843842
and the outer `<div>`, causing a double save.
844843
+makeExample('template-syntax/ts/app/app.component.html', 'event-binding-propagation')(format=".")
845844
845+
#two-way
846+
.l-main-section
847+
:marked
848+
## Two-way binding
849+
We often want to both display a data property and update that property when the user makes changes.
850+
851+
On the element side that takes a combination of setting a specific element property
852+
and listening for an element change event.
853+
854+
Angular offers a special _two-way data binding_ syntax for this purpose, **`[(x)]`**.
855+
The `[(x)]` syntax combines the brackets
856+
of _Property Binding_, `[x]`, with the parentheses of _Event Binding_, `(x)`.
857+
.callout.is-important
858+
header [( )] = banana in a box
859+
:marked
860+
Visualize a *banana in a box* to remember that the parentheses go _inside_ the brackets.
861+
:marked
862+
The `[(x)]` syntax is easy to demonstrate when the element has a settable property called `x`
863+
and a corresponding event named `xChange`.
864+
Here's a `SizerComponent` that fits the pattern.
865+
It has a `size` value property and a companion `sizeChange` event:
866+
+makeExample('template-syntax/ts/app/sizer.component.ts', null, 'app/sizer.component.ts')
867+
:marked
868+
The initial `size` is an input value from a property binding.
869+
Clicking the buttons increases or decreases the `size`, within min/max values constraints,
870+
and then raises (_emits_) the `sizeChange` event with the adjusted size.
846871

872+
Here's an example in which the `AppComponent.fontSize` is two-way bound to the `SizerComponent`:
873+
+makeExample('template-syntax/ts/app/app.component.html', 'two-way-1')(format=".")
874+
:marked
875+
The `AppComponent.fontSize` establishes the initial `SizerComponent.size` value.
876+
Clicking the buttons updates the `AppComponent.fontSize` via the two-way binding.
877+
The revised `AppComponent.fontSize` value flows through to the _style_ binding, making the displayed text bigger or smaller.
878+
Try it in the <live-example>live example</live-example>.
879+
880+
The two-way binding syntax is really just syntactic sugar for a _property_ binding and an _event_ binding.
881+
Angular _desugars_ the `SizerComponent` binding into this:
882+
+makeExample('template-syntax/ts/app/app.component.html', 'two-way-2')(format=".")
883+
:marked
884+
The `$event` variable contains the payload of the `SizerComponent.sizeChange` event.
885+
Angular assigns the `$event` value to the `AppComponent.fontSize` when the user clicks the buttons.
886+
887+
Clearly the two-way binding syntax is a great convenience compared to separate property and event bindings.
888+
889+
We'd like to use two-way binding with HTML form elements like `<input>` and `<select>`.
890+
Sadly, no native HTML element follows the `x` value and `xChange` event pattern.
891+
892+
Fortunately, the Angular [_NgModel_](#ngModel) directive is a bridge that enables two-way binding to form elements.
893+
894+
a#ngModel
847895
.l-main-section
848896
:marked
849-
<a id="ngModel"></a>
850897
## Two-way binding with NgModel
851898
When developing data entry forms, we often want to both display a data property and update that property when the user makes changes.
852899

853-
The `[(ngModel)]` two-way data binding syntax makes that easy. Here's an example:
900+
Two-way data binding with the `NgModel` directive makes that easy. Here's an example:
854901
+makeExample('template-syntax/ts/app/app.component.html', 'NgModel-1')(format=".")
855-
.callout.is-important
856-
header [()] = banana in a box
857-
:marked
858-
To remember that the parentheses go inside the brackets, visualize a *banana in a box*.
902+
859903

860904
+ifDocsFor('ts|js')
861905
.callout.is-important
@@ -865,54 +909,48 @@ block style-property-name-dart-diff
865909
we must import the `FormsModule` and add it to the Angular module's `imports` list.
866910
Learn more about the `FormsModule` and `ngModel` in the
867911
[Forms](../guide/forms.html#ngModel) chapter.
868-
912+
:marked
913+
Here's how to import the `FormsModule` to make `[(ngModel)]` available.
869914
+makeExample('template-syntax/ts/app/app.module.1.ts', '', 'app.module.ts (FormsModule import)')
870915

871916
:marked
872-
There’s a story behind this construction, a story that builds on the property and event binding techniques we learned previously.
873-
874917
### Inside `[(ngModel)]`
875-
We could have achieved the same result with separate bindings to
918+
Looking back at the `firstName` binding, it's important to note that
919+
we could have achieved the same result with separate bindings to
876920
the `<input>` element's `value` property and `input` event.
877921
+makeExample('template-syntax/ts/app/app.component.html', 'without-NgModel')(format=".")
878922
:marked
879-
That’s cumbersome. Who can remember which element property to set and what event reports user changes?
923+
That’s cumbersome. Who can remember which element property to set and which element event emits user changes?
880924
How do we extract the currently displayed text from the input box so we can update the data property?
881925
Who wants to look that up each time?
882926

883927
That `ngModel` directive hides these onerous details behind its own `ngModel` input and `ngModelChange` output properties.
884928
+makeExample('template-syntax/ts/app/app.component.html', 'NgModel-3')(format=".")
885929
.l-sub-section
886930
:marked
887-
The `ngModel` input property sets the element's value property and the `ngModelChange` output property
931+
The `ngModel` data property sets the element's value property and the `ngModelChange` event property
888932
listens for changes to the element's value.
889-
The details are specific to each kind of element and therefore the `NgModel` directive only works for elements,
890-
such as the input text box, that are supported by a [ControlValueAccessor](../api/common/index/ControlValueAccessor-interface.html).
891-
We can't apply `[(ngModel)]` to our custom components until we write a suitable *value accessor*,
933+
934+
The details are specific to each kind of element and therefore the `NgModel` directive only works for specific form elements,
935+
such as the input text box, that are supported by a [ControlValueAccessor](../api/forms/index/ControlValueAccessor-interface.html).
936+
937+
We can't apply `[(ngModel)]` to a custom component until we write a suitable *value accessor*,
892938
a technique that is beyond the scope of this chapter.
939+
That's something we might want to do for an Angular component or a WebComponent whose API we can't control.
940+
941+
It's completely unnecessary for an Angular component that we _do_ control ... because we can name the value and event properties
942+
to suit Angular's basic [two-way binding syntax](#two-way) and skip `NgModel` altogether.
893943

894944
:marked
895-
Separate `ngModel` bindings is an improvement. We can do better.
945+
Separate `ngModel` bindings is an improvement over binding to the element's native properties. We can do better.
896946

897947
We shouldn't have to mention the data property twice. Angular should be able to capture the component’s data property and set it
898-
with a single declaration &mdash; which it can with the `[( )]` syntax:
948+
with a single declaration &mdash; which it can with the `[(ngModel)]` syntax:
899949
+makeExample('template-syntax/ts/app/app.component.html', 'NgModel-1')(format=".")
900-
901-
.l-sub-section
902-
:marked
903-
`[(ngModel)]` is a specific example of a more general pattern in which Angular "de-sugars" the `[(x)]` syntax
904-
into an `x` input property for property binding and an `xChange` output property for event binding.
905-
Angular constructs the event property binding's template statement by appending `=$event`
906-
to the literal string of the template expression.
907-
908-
> <span style="font-family:courier">[(_x_)]="_e_" &lt;==> [_x_]="_e_" (<i>x</i>Change)="_e_=$event"</span>
909-
910-
We can write a two-way binding directive of our own to exploit this behavior.
911-
912950
:marked
913951
Is `[(ngModel)]` all we need? Is there ever a reason to fall back to its expanded form?
914952

915-
The `[( )]` syntax can only _set_ a data-bound property.
953+
The `[(ngModel)]` syntax can only _set_ a data-bound property.
916954
If we need to do something more or something different, we need to write the expanded form ourselves.
917955

918956
Let's try something silly like forcing the input value to uppercase:
@@ -931,8 +969,8 @@ figure.image-display
931969
The community contributed many more, and countless private directives
932970
have been created for internal applications.
933971

934-
We don’t need many of those directives in Angular 2.
935-
Quite often we can achieve the same results with the more capable and expressive Angular 2 binding system.
972+
We don’t need many of those directives in Angular.
973+
Quite often we can achieve the same results with the more capable and expressive Angular binding system.
936974
Why create a directive to handle a click when we can write a simple binding such as this?
937975
+makeExample('template-syntax/ts/app/app.component.html', 'event-binding-1')(format=".")
938976
:marked
@@ -1203,7 +1241,7 @@ block remember-the-brackets
12031241

12041242
:marked
12051243
### Expanding `*ngSwitch`
1206-
A similar transformation applies to `*ngSwitch`. We can de-sugar the syntax ourselves.
1244+
A similar transformation applies to `*ngSwitch`. We can unfold the syntax ourselves.
12071245
Here's an example, first with `*ngSwitchCase` and `*ngSwitchDefault` and then again with `<template>` tags:
12081246
+makeExample('template-syntax/ts/app/app.component.html', 'NgSwitch-expanded')(format=".")
12091247
:marked
@@ -1241,14 +1279,18 @@ figure.image-display
12411279

12421280
A **template reference variable** is a reference to a DOM element or directive within a template.
12431281

1244-
It can be used with native DOM elements but also with Angular 2 components &mdash; in fact, it will work with any custom web component.
1282+
It can be used with native DOM elements but also with Angular components &mdash; in fact, it will work with any custom web component.
12451283

12461284
:marked
12471285
### Referencing a template reference variable
12481286

1249-
We can reference a template reference variable on the same element, on a sibling element, or on
1250-
any child elements.
1287+
We can refer to a template reference variable _anywhere_ in the current template.
1288+
.l-sub-section
1289+
:marked
1290+
Do not define the same variable name more than once in the same template.
1291+
The runtime value will be unpredictable.
12511292

1293+
:marked
12521294
Here are two other examples of creating and consuming a Template reference variable:
12531295
+makeExample('template-syntax/ts/app/app.component.html', 'ref-phone')(format=".")
12541296
:marked

0 commit comments

Comments
 (0)