docs(dart/toh): add intro & toh-1 pages (#1063)
This commit is contained in:
parent
a5be02ebee
commit
a678d572ce
|
@ -0,0 +1,41 @@
|
||||||
|
// #docregion show-hero
|
||||||
|
template: '<h1>{{title}}</h1><h2>{{hero}} details!</h2>'
|
||||||
|
// #enddocregion show-hero
|
||||||
|
|
||||||
|
// #docregion show-hero-2
|
||||||
|
template: '<h1>{{title}}</h1><h2>{{hero.name}} details!</h2>'
|
||||||
|
// #enddocregion show-hero-2
|
||||||
|
|
||||||
|
// #docregion show-hero-properties
|
||||||
|
template: '<h1>{{title}}</h1><h2>{{hero.name}} details!</h2><div><label>id: </label>{{hero.id}}</div><div><label>name: </label>{{hero.name}}</div>'
|
||||||
|
// #enddocregion show-hero-properties
|
||||||
|
|
||||||
|
// #docregion multi-line-strings
|
||||||
|
template: '''
|
||||||
|
<h1>{{title}}</h1>
|
||||||
|
<h2>{{hero.name}} details!</h2>
|
||||||
|
<div><label>id: </label>{{hero.id}}</div>
|
||||||
|
<div><label>name: </label>{{hero.name}}</div>'''
|
||||||
|
// #enddocregion multi-line-strings
|
||||||
|
|
||||||
|
// #docregion editing-Hero
|
||||||
|
template: '''
|
||||||
|
<h1>{{title}}</h1>
|
||||||
|
<h2>{{hero.name}} details!</h2>
|
||||||
|
<div><label>id: </label>{{hero.id}}</div>
|
||||||
|
<div>
|
||||||
|
<label>name: </label>
|
||||||
|
<div><input value="{{hero.name}}" placeholder="name"></div>
|
||||||
|
</div>'''
|
||||||
|
// #enddocregion editing-Hero
|
||||||
|
|
||||||
|
// #docregion app-component-1
|
||||||
|
class AppComponent {
|
||||||
|
String title = 'Tour of Heroes';
|
||||||
|
Hero hero = 'Windstorm';
|
||||||
|
}
|
||||||
|
// #enddocregion app-component-1
|
||||||
|
|
||||||
|
// #docregion hero-property-1
|
||||||
|
Hero hero = new Hero(1, 'Windstorm');
|
||||||
|
// #enddocregion hero-property-1
|
|
@ -0,0 +1,28 @@
|
||||||
|
// #docregion pt1
|
||||||
|
import 'package:angular2/core.dart';
|
||||||
|
|
||||||
|
// #docregion hero-class-1
|
||||||
|
class Hero {
|
||||||
|
final int id;
|
||||||
|
String name;
|
||||||
|
|
||||||
|
Hero(this.id, this.name);
|
||||||
|
}
|
||||||
|
// #enddocregion hero-class-1
|
||||||
|
|
||||||
|
@Component(
|
||||||
|
selector: 'my-app',
|
||||||
|
template: '''
|
||||||
|
<h1>{{title}}</h1>
|
||||||
|
<h2>{{hero.name}} details!</h2>
|
||||||
|
<div><label>id: </label>{{hero.id}}</div>
|
||||||
|
<div>
|
||||||
|
<label>name: </label>
|
||||||
|
<div><input [(ngModel)]="hero.name" placeholder="name"></div>
|
||||||
|
</div>'''
|
||||||
|
)
|
||||||
|
class AppComponent {
|
||||||
|
String title = 'Tour of Heroes';
|
||||||
|
Hero hero = new Hero(1, 'Windstorm');
|
||||||
|
}
|
||||||
|
// #enddocregion pt1
|
|
@ -0,0 +1,16 @@
|
||||||
|
# #docregion
|
||||||
|
name: angular2_tour_of_heroes
|
||||||
|
version: 0.0.1
|
||||||
|
environment:
|
||||||
|
sdk: '>=1.13.0 <2.0.0'
|
||||||
|
dependencies:
|
||||||
|
angular2: 2.0.0-beta.14
|
||||||
|
browser: ^0.10.0
|
||||||
|
dart_to_js_script_rewriter: ^1.0.1
|
||||||
|
transformers:
|
||||||
|
- angular2:
|
||||||
|
platform_directives:
|
||||||
|
- package:angular2/common.dart#COMMON_DIRECTIVES
|
||||||
|
platform_pipes:
|
||||||
|
- package:angular2/common.dart#COMMON_PIPES
|
||||||
|
entry_points: web/main.dart
|
|
@ -0,0 +1,14 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Angular 2 Tour of Heroes</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
|
||||||
|
<script defer src="main.dart" type="application/dart"></script>
|
||||||
|
<script defer src="packages/browser/dart.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<my-app>Loading...</my-app>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,9 @@
|
||||||
|
// #docregion pt1
|
||||||
|
import 'package:angular2/bootstrap.dart';
|
||||||
|
|
||||||
|
import 'package:angular2_tour_of_heroes/app_component.dart';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
bootstrap(AppComponent);
|
||||||
|
}
|
||||||
|
// #enddocregion pt1
|
|
@ -2,7 +2,7 @@
|
||||||
"index": {
|
"index": {
|
||||||
"title": "Tutorial: Tour of Heroes",
|
"title": "Tutorial: Tour of Heroes",
|
||||||
"navTitle": "Introduction",
|
"navTitle": "Introduction",
|
||||||
"intro": "The Tour of Heroes tutorial takes us through the steps of creating an Angular application in TypeScript.",
|
"intro": "The Tour of Heroes tutorial takes us through the steps of creating an Angular application in Dart.",
|
||||||
"nextable": true
|
"nextable": true
|
||||||
},
|
},
|
||||||
"toh-pt1": {
|
"toh-pt1": {
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
include ../_util-fns
|
include ../_util-fns
|
||||||
|
|
||||||
|
+includeShared('{ts}', 'intro')
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
We're working on the Dart version of this case study.
|
[View the source code](https://github.com/angular/angular.io/tree/master/public/docs/_examples/toh-5/dart)
|
||||||
In the meantime, please see these resources:
|
|
||||||
|
|
||||||
* [Introduction](/docs/ts/latest/tutorial/index.html):
|
+includeShared('{ts}', 'main')
|
||||||
The TypeScript version of this chapter
|
|
||||||
|
|
||||||
* [Dart source code](https://github.com/angular/angular.io/tree/master/public/docs/_examples/toh-5/dart):
|
|
||||||
A preliminary Dart version of the Tour of Heroes app,
|
|
||||||
featuring the hero editor, master/detail views,
|
|
||||||
multiple components, services, and routing
|
|
||||||
|
|
|
@ -1,14 +1,189 @@
|
||||||
include ../_util-fns
|
include ../_util-fns
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
We're working on the Dart version of this case study.
|
# Once Upon a Time
|
||||||
In the meantime, please see these resources:
|
|
||||||
|
|
||||||
* [The Hero Editor](/docs/ts/latest/tutorial/toh-pt1.html):
|
Every story starts somewhere. Our story starts where the [QuickStart](../quickstart.html) ends.
|
||||||
The TypeScript version of this chapter
|
|
||||||
|
|
||||||
* [Dart source code](https://github.com/angular/angular.io/tree/master/public/docs/_examples/toh-5/dart):
|
:marked
|
||||||
A preliminary Dart version of the Tour of Heroes app,
|
Follow the "QuickStart" steps. They provide the prerequisites, the folder structure,
|
||||||
featuring the hero editor, a master/detail page,
|
and the core files for our Tour of Heroes.
|
||||||
multiple components, services, and routing
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
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 pubspec.yaml
|
||||||
|
|
||||||
|
// Add .file styles.css
|
||||||
|
|
||||||
|
.p
|
||||||
|
|
||||||
|
.callout.is-helpful
|
||||||
|
header Source code
|
||||||
|
:marked
|
||||||
|
The complete source code for the example app in this chapter is
|
||||||
|
[in GitHub](https://github.com/angular/angular.io/tree/master/public/docs/_examples/toh-1/dart).
|
||||||
|
|
||||||
|
: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(format="" 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, 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".
|
||||||
|
|
||||||
|
+makeExample('toh-1/dart-snippets/app_component_snippets_pt1.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 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.
|
||||||
|
|
||||||
|
### 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).
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
include ../_util-fns
|
include ../_util-fns
|
||||||
|
|
||||||
|
// #docregion intro
|
||||||
:marked
|
:marked
|
||||||
# Tour of Heroes: the vision
|
# Tour of Heroes: the vision
|
||||||
|
|
||||||
|
@ -23,9 +24,11 @@ include ../_util-fns
|
||||||
Angular can do whatever we need it to do.
|
Angular can do whatever we need it to do.
|
||||||
We'll be covering a lot of ground at an introductory level but we’ll find plenty of links
|
We'll be covering a lot of ground at an introductory level but we’ll find plenty of links
|
||||||
to chapters with greater depth.
|
to chapters with greater depth.
|
||||||
|
// #enddocregion intro
|
||||||
|
|
||||||
[Run the live example](/resources/live-examples/tutorial/ts/plnkr.html)
|
[Run the live example](/resources/live-examples/tutorial/ts/plnkr.html)
|
||||||
|
|
||||||
|
// #docregion main
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## The End Game
|
## The End Game
|
||||||
|
@ -82,3 +85,4 @@ figure.image-display
|
||||||
And we’ll meet many of the core fundamentals of Angular along the way.
|
And we’ll meet many of the core fundamentals of Angular along the way.
|
||||||
|
|
||||||
[Let's get started!](./toh-pt1.html)
|
[Let's get started!](./toh-pt1.html)
|
||||||
|
// #enddocregion main
|
||||||
|
|
Loading…
Reference in New Issue