angular-docs-cn/public/docs/dart/latest/tutorial/toh-pt1.jade

188 lines
6.7 KiB
Plaintext
Raw Normal View History

include ../_util-fns
:marked
# Once Upon a Time
Every story starts somewhere. Our story starts where the [QuickStart](../quickstart.html) ends.
: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
.file styles.css
.file pubspec.yaml
.p &nbsp;
.callout.is-helpful
header Source code
:marked
Run the <live-example></live-example> for this part.
: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
code-example(language="bash").
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, lets refactor our components `hero` property to be of type `Hero`.
Then initialize it with an id of `1` and the name, "Windstorm".
+makeExample('toh-1/dart/lib/app_component.dart', 'hero-property-1', 'app_component.dart (hero property)')(format=".")
:marked
Because we changed the hero from a string to an object,
we update the binding in the template to refer to the heros `name` property.
+makeExample('toh-1/dart-snippets/app_component_snippets_pt1.dart', 'show-hero-2')
:marked
The browser refreshes and continues to display our heros name.
### Adding more HTML
Displaying a name is good, but we want to see all of our heros properties.
Well add a `<div>` for our heros `id` property and another `<div>` for our heros `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,
lets 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 heros name does appear in the `<input>` textbox.
But something doesnt 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 heros name.
In short, we want two-way data binding.
Lets 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").
&lt;input [(ngModel)]="hero.name" placeholder="name">
:marked
The browser refreshes. We see our hero again. We can edit the heros name and
see the changes reflected immediately in the `<h2>`.
.l-main-section
:marked
## The Road Weve Travelled
Lets take stock of what weve 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 heros 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.
Well 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).