Build a simple hero editor.
Follow the setup instructions for creating a new project named
The file structure should look like this:
angular-tour-of-heroes src app app.component.ts app.module.ts main.ts index.html styles.css systemjs.config.js tsconfig.json node_modules ... package.json
When you're done with this page, the app should look like this live example.
Enter the following command in the terminal window:
npm start
This command runs the TypeScript compiler in "watch mode", recompiling automatically when the code changes. The command simultaneously launches the app in a browser and refreshes the browser when the code changes.
You can keep building the Tour of Heroes without pausing to recompile or refresh the browser.
Add two properties to the AppComponent
: a title
property for the app name and a hero
property for a hero named "Windstorm."
export class AppComponent { title = 'Tour of Heroes'; hero = 'Windstorm'; }
Now update the template in the @Component
decorator with data bindings to these new properties.
template: `<h1>{{title}}</h1><h2>{{hero}} details!</h2>`
The browser refreshes and displays the title and hero name.
The double curly braces are Angular's interpolation binding syntax. These interpolation bindings present the component's title
and hero
property values, as strings, inside the HTML header tags.
Read more about interpolation in the Displaying Data page.
The hero needs more properties. Convert the hero
from a literal string to a class.
Create a Hero
class with id
and name
properties. Add these properties near the top of the app.component.ts
file, just below the import statement.
export class Hero { id: number; name: string; }
In the Hero
class, refactor the component's hero
property to be of type Hero
, then initialize it with an id
of 1
and the name Windstorm
.
hero: Hero = { id: 1, name: 'Windstorm' };
Because you changed the hero from a string to an object, update the binding in the template to refer to the hero's name
property.
template: `<h1>{{title}}</h1><h2>{{hero.name}} details!</h2>`
The browser refreshes and continues to display the hero's name.
To show all of the hero's properties, add a <div>
for the hero's id
property and another <div>
for the hero's name
. To keep the template readable, place each <div>
on its own line.
The backticks around the component template let you put the <h1>
, <h2>
, and <div>
elements on their own lines, thanks to the template literals feature in ES2015 and TypeScript. For more information, see Template literals.
template: ` <h1>{{title}}</h1> <h2>{{hero.name}} details!</h2> <div><label>id: </label>{{hero.id}}</div> <div><label>name: </label>{{hero.name}}</div> `
Users should be able to edit the hero name in an <input>
textbox. The textbox should both display the hero's name
property and update that property as the user types.
You need a two-way binding between the <input>
form element and the hero.name
property.
Refactor the hero name in the template so it looks like this:
<div> <label>name: </label> <input [(ngModel)]="hero.name" placeholder="name"> </div>
[(ngModel)]
is the Angular syntax to bind the hero.name
property to the textbox. Data flow in both directions: from the property to the textbox; and from the textbox back to the property.
Unfortunately, immediately after this change, the application breaks. If you looked in the browser console, you'd see Angular complaining that "ngModel
... isn't a known property of input
."
Although NgModel
is a valid Angular directive, it isn't available by default. It belongs to the optional FormsModule
. You must opt-in to using that module.
Open the app.module.ts
file and import the FormsModule
symbol from the @angular/forms
library. Then add the FormsModule
to the @NgModule
metadata's imports
array, which contains the list of external modules that the app uses.
The updated AppModule
looks like this:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; // <-- NgModel lives here import { AppComponent } from './app.component'; @NgModule({ imports: [ BrowserModule, FormsModule // <-- import the FormsModule before binding with [(ngModel)] ], declarations: [ AppComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }
Read more about
FormsModule
andngModel
in the Two-way data binding with ngModel section of the Forms guide and the Two-way binding with NgModel section of the Template Syntax guide.
When the browser refreshes, the app should work again. You can edit the hero's name and see the changes reflected immediately in the <h2>
above the textbox.
Take stock of what you've built.
Hero
object.<input>
element using the built-in ngModel
directive. This binding both displays the hero's name and allows users to change it.ngModel
directive propagates changes to every other binding of the hero.name
.Your app should look like this live example.
Here's the complete app.component.ts
as it stands now:
import { Component } from '@angular/core'; export class Hero { id: number; name: string; } @Component({ selector: 'my-app', template: ` <h1>{{title}}</h1> <h2>{{hero.name}} details!</h2> <div><label>id: </label>{{hero.id}}</div> <div> <label>name: </label> <input [(ngModel)]="hero.name" placeholder="name"> </div> ` }) export class AppComponent { title = 'Tour of Heroes'; hero: Hero = { id: 1, name: 'Windstorm' }; }
In the next tutorial page, you'll build on the Tour of Heroes app to display a list of heroes. You'll also allow the user to select heroes and display their details. You'll learn more about how to retrieve lists and bind them to the template.
Next Step
Master/Detail
© 2010–2017 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://v2.angular.io/docs/ts/latest/tutorial/toh-pt1.html