| 
									
										
										
										
											2016-03-16 14:39:06 -04:00
										 |  |  |  | include ../_util-fns | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-04-07 21:11:13 -07:00
										 |  |  |  |   # Once Upon a Time | 
					
						
							| 
									
										
										
										
											2016-03-16 14:39:06 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-07 21:11:13 -07:00
										 |  |  |  |   Every story starts somewhere. Our story starts where the [QuickStart](../quickstart.html) ends. | 
					
						
							| 
									
										
										
										
											2016-03-16 14:39:06 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-07 21:11:13 -07:00
										 |  |  |  | :marked | 
					
						
							|  |  |  |  |   Follow the "QuickStart" steps. They provide the prerequisites, the folder structure, | 
					
						
							|  |  |  |  |   and the core files for our Tour of Heroes. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   <!-- | 
					
						
							|  |  |  |  |     TODO: Recommend stagehand? | 
					
						
							|  |  |  |  |   --> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   Copy the "QuickStart" code to a new folder and rename the folder `angular2_tour_of_heroes`. | 
					
						
							|  |  |  |  |   We should have the following structure: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | .filetree | 
					
						
							|  |  |  |  |   .file angular2_tour_of_heroes | 
					
						
							|  |  |  |  |   .children | 
					
						
							|  |  |  |  |     .file lib | 
					
						
							|  |  |  |  |     .children | 
					
						
							|  |  |  |  |       .file app_component.dart | 
					
						
							|  |  |  |  |     .file web | 
					
						
							|  |  |  |  |     .children | 
					
						
							|  |  |  |  |       .file index.html | 
					
						
							|  |  |  |  |       .file main.dart | 
					
						
							| 
									
										
										
										
											2016-06-15 10:49:42 -07:00
										 |  |  |  |       .file styles.css | 
					
						
							| 
									
										
										
										
											2016-04-07 21:11:13 -07:00
										 |  |  |  |     .file pubspec.yaml | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | .p   | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | .callout.is-helpful | 
					
						
							|  |  |  |  |   header Source code | 
					
						
							| 
									
										
										
										
											2016-07-03 17:11:17 -07:00
										 |  |  |  |   :marked | 
					
						
							|  |  |  |  |     Run the <live-example></live-example> for this part. | 
					
						
							| 
									
										
										
										
											2016-04-07 21:11:13 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | :marked | 
					
						
							|  |  |  |  |   ## Keep the app compiling and running | 
					
						
							|  |  |  |  |   We want to start the Dart compiler, have it watch for changes, and start our server. We'll do this by typing | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-07 15:51:25 -07:00
										 |  |  |  | code-example(language="bash"). | 
					
						
							| 
									
										
										
										
											2016-04-07 21:11:13 -07:00
										 |  |  |  |   pub serve | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | :marked | 
					
						
							|  |  |  |  |   This command runs the compiler in watch mode, starts the server, | 
					
						
							|  |  |  |  |   and keeps the app running while we continue to build the Tour of Heroes. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | .l-main-section | 
					
						
							|  |  |  |  |   :marked | 
					
						
							|  |  |  |  |     ## Show our Hero | 
					
						
							|  |  |  |  |     We want to display Hero data in our app. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     Let's add two properties to our `AppComponent`, a `title` property for the application name and a `hero` property | 
					
						
							|  |  |  |  |     for a hero named "Windstorm". | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   +makeExample('toh-1/dart-snippets/app_component_snippets_pt1.dart', 'app-component-1', 'app_component.dart (AppComponent class)')(format=".") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   :marked | 
					
						
							|  |  |  |  |     Now we update the template in the `@Component` annotation with data bindings to these new properties. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   +makeExample('toh-1/dart-snippets/app_component_snippets_pt1.dart', 'show-hero') | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   :marked | 
					
						
							|  |  |  |  |     The browser should refresh and display our title and hero. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     The double curly braces tell our app to read the `title` and `hero` properties from the component and render them. | 
					
						
							|  |  |  |  |     This is the "interpolation" form of one-way data binding. | 
					
						
							|  |  |  |  | .l-sub-section | 
					
						
							|  |  |  |  |   :marked | 
					
						
							|  |  |  |  |     Learn more about interpolation in the [Displaying Data chapter](../guide/displaying-data.html). | 
					
						
							|  |  |  |  | :marked | 
					
						
							|  |  |  |  |   ### Hero object | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   At the moment, our hero is just a name.  Our hero needs more properties. | 
					
						
							|  |  |  |  |   Let's convert the `hero` from a literal string to a class. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   Create a `Hero` class with `id` and `name` properties. | 
					
						
							|  |  |  |  |   Keep this near the top of the `app_component.dart` file for now. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | +makeExample('toh-1/dart/lib/app_component.dart', 'hero-class-1', 'app_component.dart (Hero class)')(format=".") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | :marked | 
					
						
							|  |  |  |  |   Now that we have a `Hero` class, let’s refactor our component’s `hero` property to be of type `Hero`. | 
					
						
							|  |  |  |  |   Then initialize it with an id of `1` and the name, "Windstorm". | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-07 14:59:41 -07:00
										 |  |  |  | +makeExample('toh-1/dart/lib/app_component.dart', 'hero-property-1', 'app_component.dart (hero property)')(format=".") | 
					
						
							| 
									
										
										
										
											2016-04-07 21:11:13 -07:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | :marked | 
					
						
							|  |  |  |  |   Because we changed the hero from a string to an object, | 
					
						
							|  |  |  |  |   we update the binding in the template to refer to the hero’s `name` property. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | +makeExample('toh-1/dart-snippets/app_component_snippets_pt1.dart', 'show-hero-2') | 
					
						
							|  |  |  |  | :marked | 
					
						
							|  |  |  |  |   The browser refreshes and continues to display our hero’s name. | 
					
						
							| 
									
										
										
										
											2016-03-16 14:39:06 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-07 21:11:13 -07:00
										 |  |  |  |   ### Adding more HTML | 
					
						
							|  |  |  |  |   Displaying a name is good, but we want to see all of our hero’s properties. | 
					
						
							|  |  |  |  |   We’ll add a `<div>` for our hero’s `id` property and another `<div>` for our hero’s `name`. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | +makeExample('toh-1/dart-snippets/app_component_snippets_pt1.dart', 'show-hero-properties') | 
					
						
							|  |  |  |  | :marked | 
					
						
							|  |  |  |  |   Uh oh, our template string is getting long. We better take care of that to avoid the risk of making a typo in the template. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   ### Multi-line template strings | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   We could make a more readable template with string concatenation | 
					
						
							|  |  |  |  |   but that gets ugly fast, it is harder to read, and | 
					
						
							|  |  |  |  |   it is easy to make a spelling error. Instead, | 
					
						
							|  |  |  |  |   let’s take advantage of the template strings feature | 
					
						
							|  |  |  |  |   in Dart to maintain our sanity. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   Change the quotes around the template to triple quotes and | 
					
						
							|  |  |  |  |   put the `<h1>`, `<h2>` and `<div>` elements on their own lines. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | +makeExample('toh-1/dart-snippets/app_component_snippets_pt1.dart', 'multi-line-strings', 'app_component.dart (AppComponent\'s template)')(format=".") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // omit back-tick warning | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | .l-main-section | 
					
						
							|  |  |  |  | :marked | 
					
						
							|  |  |  |  |   ## Editing Our Hero | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   We want to be able to edit the hero name in a textbox. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   Refactor the hero name `<label>` with `<label>` and `<input>` elements as shown below: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | +makeExample('toh-1/dart-snippets/app_component_snippets_pt1.dart', 'editing-Hero', 'app_component.dart (input element)')(format=".") | 
					
						
							|  |  |  |  | :marked | 
					
						
							|  |  |  |  |   We see in the browser that the hero’s name does appear in the `<input>` textbox. | 
					
						
							|  |  |  |  |   But something doesn’t feel right. | 
					
						
							|  |  |  |  |   When we change the name, we notice that our change | 
					
						
							|  |  |  |  |   is not reflected in the `<h2>`. We won't get the desired behavior | 
					
						
							|  |  |  |  |   with a one-way binding to `<input>`. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   ### Two-Way Binding | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   We intend to display the name of the hero in the `<input>`, change it, | 
					
						
							|  |  |  |  |   and see those changes wherever we bind to the hero’s name. | 
					
						
							|  |  |  |  |   In short, we want two-way data binding. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   Let’s update the template to use the  **`ngModel`** built-in directive for two-way binding. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | .l-sub-section | 
					
						
							|  |  |  |  |   :marked | 
					
						
							|  |  |  |  |     Learn more about `ngModel` in the | 
					
						
							|  |  |  |  |     [Forms](../guide/forms.html#ngModel) and | 
					
						
							|  |  |  |  |     [Template Syntax](../guide/template-syntax.html#ngModel) chapters. | 
					
						
							|  |  |  |  | :marked | 
					
						
							|  |  |  |  |   Replace the `<input>` with the following HTML | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | code-example(language="html"). | 
					
						
							|  |  |  |  |   <input [(ngModel)]="hero.name" placeholder="name"> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | :marked | 
					
						
							|  |  |  |  |   The browser refreshes. We see our hero again. We can edit the hero’s name and | 
					
						
							|  |  |  |  |   see the changes reflected immediately in the `<h2>`. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | .l-main-section | 
					
						
							|  |  |  |  | :marked | 
					
						
							|  |  |  |  |   ## The Road We’ve Travelled | 
					
						
							|  |  |  |  |   Let’s take stock of what we’ve built. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   * Our Tour of Heroes uses the double curly braces of interpolation (a form of one-way data binding) | 
					
						
							|  |  |  |  |   to display the application title and properties of a `Hero` object. | 
					
						
							|  |  |  |  |   * We wrote a multi-line template using Dart's template strings to make our template readable. | 
					
						
							|  |  |  |  |   * We can both display and change the hero’s name after adding a two-way data binding to the `<input>` element | 
					
						
							|  |  |  |  |   using the built-in `ngModel` directive. | 
					
						
							|  |  |  |  |   * The `ngModel` directive also propagates changes to every other binding of the `hero.name`. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   <!-- TODO: | 
					
						
							|  |  |  |  |     add [Run the live example for part 1](https://tour-of-heroes.firebaseapp.com/toh1/) | 
					
						
							|  |  |  |  |   --> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   Here's the complete `app_component.dart` as it stands now: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | +makeExample('toh-1/dart/lib/app_component.dart', 'pt1', 'app_component.dart') | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | .l-main-section | 
					
						
							|  |  |  |  | :marked | 
					
						
							|  |  |  |  |   ## The Road Ahead | 
					
						
							|  |  |  |  |   Our Tour of Heroes only displays one hero and we really want to display a list of heroes. | 
					
						
							|  |  |  |  |   We also want to allow the user to select a hero and display their details. | 
					
						
							|  |  |  |  |   We’ll learn more about how to retrieve lists, bind them to the | 
					
						
							|  |  |  |  |   template, and allow a user to select it in the | 
					
						
							|  |  |  |  |   [next tutorial chapter](./toh-pt2.html). |