Setup to develop locally


Follow the setup instructions for creating a new project named angular-tour-of-heroes.


The file structure should look like this:


node_modules ...

When you're done with this page, the app should look like this .


Keep the app transpiling and running


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.

这个命令会在“监听”模式下运行TypeScript编译器,当代码变化时,它会自动重新编译。 同时,该命令还会在浏览器中启动该应用,并且当代码变化时刷新浏览器。

You can keep building the Tour of Heroes without pausing to recompile or refresh the browser.


Show the hero


Add two properties to the AppComponent: a title property for the app name and a hero property for a hero named "Windstorm."


app.component.ts (AppComponent class)

export class AppComponent { title = 'Tour of Heroes'; hero = 'Windstorm'; }

Now update the template in the @Component decorator with data bindings to these new properties.


app.component.ts (@Component)

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.


Hero object

Hero 对象

The hero needs more properties. Convert the hero from a literal string to a class.

显然,英雄还需要更多属性。 让我们把hero从一个字符串字面量换成一个类。

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.

创建一个Hero类,它具有idname属性。 现在,把下列代码放在app.component.ts的顶部,仅次于 import 语句。

src/app/app.component.ts (Hero class)

export class Hero { id: number; name: string; }

In the AppComponent 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属性的类型换成Hero。 然后以1为 id、以 “Windstorm” 为名字,初始化它。

src/app/app.component.ts (hero property)

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.


Adding HTML with multi-line template strings

使用多行模板字符串添加更多 HTML

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.

要显示英雄的所有属性,还要为英雄的id属性添加一个<div>,为英雄的name属性添加另一个<div>。 为了保持模板的可读性,把每个<div>单独放一行。

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.

反引号包裹的组件模板能让你把<h1><h2><div>元素各自放在一行上。 感谢ES2015和TypeScript的模板字面量特性。要了解更多,请参见模板字面量(Template literals) 页。

app.component.ts (AppComponent's template)

template: ` <h1>{{title}}</h1> <h2>{{hero.name}} details!</h2> <div><label>id: </label>{{hero.id}}</div> <div><label>name: </label>{{hero.name}}</div> `

Edit the hero name


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.

用户应该能在一个<input>输入框中编辑英雄的名字。 当用户输入时,这个输入框应该能同时显示修改英雄的name属性。

You need a two-way binding between the <input> form element and the hero.name property.


Two-way binding


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 flows in both directions: from the property to the textbox, and from the textbox back to the property.

[(ngModel)]是一个Angular语法,用与把hero.name绑定到输入框中。 它的数据流是双向的:从属性到输入框,并且从输入框回到属性。

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."

不幸的是,做了这项改动之后,我们的程序崩溃了。 打开浏览器的控制台,我们会看到Angular抱怨说:“ngModel ... isn't a known property of input.”(ngModel不是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.

虽然NgModel是一个有效的Angular指令,但它默认情况下却是不可用的。 它属于一个可选模块FormsModule。 我们必须选择使用那个模块。

Import the FormsModule

导入 FormsModule

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.

打开app.module.ts文件,并且从@angular/forms库中导入符号FormsModule。 然后把FormsModule添加到@NgModule元数据的imports数组中,它是当前应用正在使用的外部模块列表。

The updated AppModule looks like this:


app.module.ts (FormsModule import)

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 and ngModel 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.


The road you've travelled


Take stock of what you've built.


Your app should look like this .


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' }; }

The road ahead


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.

教程的下一章,我们将在这个《英雄指南》中显示一个英雄列表。 我们将允许允许用户选择一个英雄,并且显示它/她的详情。 我们还将学会如何获取列表以及将它们绑定到模板中。