@@ -42,12 +42,12 @@ code-example(language="sh" class="code-shell").
42
42
add two properties to the `AppComponent`: a `title` property for the app name and a `hero` property
43
43
for a hero named "Windstorm."
44
44
45
- + makeExample('toh-1/ts-snippets /app.component.snippets.pt1 .ts' , 'app-component-1' , 'app.component.ts (AppComponent class)' )( format ="." )
45
+ + makeExample('toh-1/ts/app/app .component.1 .ts' , 'app-component-1' , 'app.component.ts (AppComponent class)' )( format ="." )
46
46
47
47
:marked
48
48
Now update the template in the `@Component` decoration with data bindings to these new properties.
49
49
50
- + makeExample('toh-1/ts-snippets /app.component.snippets.pt1. ts' , 'show-hero' )
50
+ + makeExample('toh-1/ts/app/app .component.1. ts' , 'show-hero' , 'app.component.ts (@Component)' ) ( format = '. ')
51
51
52
52
:marked
53
53
The browser refreshes and displays the title and hero name.
@@ -79,7 +79,7 @@ code-example(language="sh" class="code-shell").
79
79
Because you changed the hero from a string to an object,
80
80
update the binding in the template to refer to the hero's `name` property.
81
81
82
- + makeExample('toh-1/ts-snippets /app.component.snippets.pt1 .ts' , 'show-hero-2' )
82
+ + makeExample('toh-1/ts/app/app .component.1 .ts' , 'show-hero-2' )
83
83
:marked
84
84
The browser refreshes and continues to display the hero's name.
85
85
@@ -92,56 +92,56 @@ code-example(language="sh" class="code-shell").
92
92
change the quotes around the template to backticks
93
93
and put the `<h1>`, `<h2>`, and `<div>` elements on their own lines.
94
94
95
- + makeExample('toh-1/ts-snippets /app.component.snippets.pt1. ts' , 'multi-line-strings' , 'app.component.ts (AppComponent\' s template)' )
95
+ + makeExample('toh-1/ts/app/app .component.1. ts' , 'multi-line-strings' , 'app.component.ts (AppComponent\' s template)' ) ( format = '. ')
96
96
97
97
.l-main-section
98
98
:marked
99
99
## Editing the hero name
100
100
101
- Users should be able to edit the hero name in a textbox.
101
+ Users should be able to edit the hero name in an `<input>` textbox.
102
+ The textbox should both _display_ the hero's `name` property
103
+ and _update_ that property as the user types.
102
104
103
- Refactor the hero name `<label>` with `<label >` and `<input>` elements .
105
+ You need a two-way binding between the `<input >` form element and the `hero.name` property .
104
106
105
- + makeExample('toh-1/ts-snippets/app.component.snippets.pt1.ts' , 'editing-Hero' , 'app.component.ts (input element)' )
107
+ ### Two-way binding
108
+
109
+ Refactor the hero name in the template so it looks like this:
110
+ + makeExample('toh-1/ts/app/app.component.1.ts' , 'name-input' )( format ='.' )
106
111
:marked
107
- The hero's name now appears in the `<input>` textbox,
108
- but if you change the name, the change
109
- isn't reflected in the `<h2>`. To get the desired behavior,
110
- you can implement two-way binding .
112
+ `[(ngModel)]` is the Angular syntax to bind the `hero.name` property
113
+ to the textbox.
114
+ Data flow _in both directions_: from the property to the textbox;
115
+ and from the textbox back to the property .
111
116
112
- ### Two-way binding
117
+ Unfortunately, immediately after this change, the application breaks.
118
+ If you looked in the browser console, you'd see Angular complaining that
119
+ " 'ngModel' ... isn't a known property of 'input'."
113
120
114
- When users change the name of the hero in the `<input>`,
115
- the changes should appear in any place where the hero's name is bound .
116
- This is known as two-way data binding .
121
+ Although `NgModel` is a valid Angular directive, it isn't available by default.
122
+ It belongs to the optional `FormsModule` .
123
+ You must opt-in to using that module .
117
124
118
- Before using two-way data binding for *form inputs*, import the `FormsModule`
119
- package in the Angular module. Add the `FormsModule` to the `NgModule` decorator's `imports` array, which contains the list
120
- of external modules that the app uses.
121
- Now you have included the forms package that includes `ngModel`.
125
+ ### Import the _FormsModule_
122
126
127
+ Open the `app.module.ts` file and import the `FormsModule` symbol from the `@angular/forms` library.
128
+ Then add the `FormsModule` to the `NgModule` metadata's `imports` array, which contains the list
129
+ of external modules that the app uses.
130
+
131
+ The updated `AppModule` looks like this:
123
132
+ makeExample('toh-1/ts/app/app.module.ts' , '' , 'app.module.ts (FormsModule import)' )
124
133
125
134
.l-sub-section
126
135
:marked
127
136
Read more about `FormsModule` and `ngModel` in the
128
- [Two-way data binding with ngModel](../guide/forms.html#ngModel) section of the
129
- [Forms](../guide/forms.html) page and the
130
- [Two-way binding with NgModel](../guide/template-syntax.html#ngModel) section of the
131
- [Template Syntax](../guide/template-syntax.html)
132
- page.
133
-
134
-
135
- :marked
136
- Update the template to use the `ngModel` built-in directive for two-way binding.
137
- In app.component.ts, replace the `<input>` with the following HTML:
138
-
139
- code-example( language ="html" ) .
140
- < input [(ngModel)]="hero.name" placeholder="name">
137
+ [_Two-way data binding with ngModel_](../guide/forms.html#ngModel) section of the
138
+ [Forms](../guide/forms.html) guide and the
139
+ [_Two-way binding with NgModel_](../guide/template-syntax.html#ngModel) section of the
140
+ [Template Syntax](../guide/template-syntax.html) guide.
141
141
142
142
:marked
143
- When the browser refreshes, you can edit the hero's name and
144
- see the changes reflected immediately in the `<h2>`.
143
+ When the browser refreshes, the app should work again.
144
+ You can edit the hero's name and see the changes reflected immediately in the `<h2>` above the textbox .
145
145
146
146
.l-main-section
147
147
:marked
@@ -150,7 +150,7 @@ code-example(language="html").
150
150
151
151
* The Tour of Heroes app uses the double curly braces of interpolation (a type of one-way data binding)
152
152
to display the app title and properties of a `Hero` object.
153
- * You wrote a multi-line template using ES2015's template strings to make the template readable.
153
+ * You wrote a multi-line template using ES2015's template literals to make the template readable.
154
154
* You added a two-way data binding to the `<input>` element
155
155
using the built-in `ngModel` directive. This binding both displays the hero's name and allows users to change it.
156
156
* The `ngModel` directive propagates changes to every other binding of the `hero.name`.
@@ -159,7 +159,7 @@ code-example(language="html").
159
159
160
160
Here's the complete `app.component.ts` as it stands now:
161
161
162
- + makeExample('toh-1/ts/app/app.component.ts' , 'pt1 ' , 'app.component.ts' )
162
+ + makeExample('toh-1/ts/app/app.component.ts' , '' , 'app.component.ts' )
163
163
164
164
.l-main-section
165
165
:marked
0 commit comments