include ../_util-fns :marked In this page, you'll expand the Tour of Heroes app to display a list of heroes, and allow users to select a hero and display the hero's details. When you're done with this page, the app should look like this . .l-main-section :marked ## Where you left off Before you continue with this page of the Tour of Heroes, verify that you have the following structure after [The Hero Editor](./toh-pt1.html) page. If your structure doesn't match, go back to that page to figure out what you missed. .filetree .file angular-tour-of-heroes .children .file src .children .file app .children .file app.component.ts .file app.module.ts .file main.ts .file index.html .file styles.css .file systemjs.config.js .file tsconfig.json .file node_modules ... .file package.json :marked ## Keep the app transpiling and running Enter the following command in the terminal window: code-example(language="sh" class="code-shell"). npm start :marked 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. .l-main-section :marked ## Displaying heroes To display a list of heroes, you'll add heroes to the view's template. ### Create heroes Create an array of ten heroes. +makeExample('toh-2/ts/src/app/app.component.ts', 'hero-array', 'src/app/app.component.ts (hero array)') :marked The `HEROES` array is of type `Hero`, the class defined in the previous page. Eventually this app will fetch the list of heroes from a web service, but for now you can display mock heroes. ### Expose heroes Create a public property in `AppComponent` that exposes the heroes for binding. +makeExample('toh-2/ts/app/app.component.1.html', 'hero-array-1', 'app.component.ts (hero array property)') :marked The `heroes` type isn't defined because TypeScript infers it from the `HEROES` array. .l-sub-section :marked The hero data is separated from the class implementation because ultimately the hero names will come from a data service. :marked ### Display hero names in a template To display the hero names in an unordered list, insert the following chunk of HTML below the title and above the hero details. +makeExample('toh-2/ts/app/app.component.1.html', 'heroes-template-1', 'app.component.ts (heroes template)')(format='.') :marked Now you can fill the template with hero names. ### List heroes with ngFor The goal is to bind the array of `heroes` in the component to the template, iterate over them, and display them individually. Modify the `
  • ` tag by adding the built-in directive `*ngFor`. +makeExample('toh-2/ts/app/app.component.1.html', 'heroes-ngfor-1', 'app.component.ts (ngFor)') .l-sub-section :marked The (`*`) prefix to `ngFor` is a critical part of this syntax. It indicates that the `
  • ` element and its children constitute a master template. The `ngFor` directive iterates over the component's `heroes` array and renders an instance of this template for each hero in that array. The `let hero` part of the expression identifies `hero` as the template input variable, which holds the current hero item for each iteration. You can reference this variable within the template to access the current hero's properties. Read more about `ngFor` and template input variables in the [Showing an array property with *ngFor](../guide/displaying-data.html#ngFor) section of the [Displaying Data](../guide/displaying-data.html) page and the [ngFor](../guide/template-syntax.html#ngFor) section of the [Template Syntax](../guide/template-syntax.html) page. :marked Within the `
  • ` tags, add content that uses the `hero` template variable to display the hero's properties. +makeExample('toh-2/ts/app/app.component.1.html', 'ng-for', 'app.component.ts (ngFor template)')(format=".") :marked When the browser refreshes, a list of heroes appears. ### Style the heroes Users should get a visual cue of which hero they are hovering over and which hero is selected. To add styles to your component, set the `styles` property on the `@Component` decorator to the following CSS classes: +makeExample('toh-2/ts/src/app/app.component.ts', 'styles', 'src/app/app.component.ts (styles)')(format=".") :marked Remember to use the backtick notation for multi-line strings. Adding these styles makes the file much longer. In a later page you'll move the styles to a separate file. When you assign styles to a component, they are scoped to that specific component. These styles apply only to the `AppComponent` and don't affect the outer HTML. The template for displaying heroes should look like this: +makeExample('toh-2/ts/app/app.component.1.html', 'heroes-styled', 'src/app/app.component.ts (styled heroes)')(format='.') .l-main-section :marked ## Selecting a hero The app now displays a list of heroes as well as a single hero in the details view. But the list and the details view are not connected. When users select a hero from the list, the selected hero should appear in the details view. This UI pattern is known as "master/detail." In this case, the _master_ is the heroes list and the _detail_ is the selected hero. Next you'll connect the master to the detail through a `selectedHero` component property, which is bound to a click event. ### Add a click event Add a click event binding to the `
  • ` like this: +makeExample('toh-2/ts/app/app.component.1.html', 'selectedHero-click', 'app.component.ts (template excerpt)')(format='.') :marked The parentheses identify the `
  • ` element's `click` event as the target. The `onSelect(hero)` expression calls the `AppComponent` method, `onSelect()`, passing the template input variable `hero`, as an argument. That's the same `hero` variable you defined previously in the `ngFor` directive. .l-sub-section :marked Learn more about event binding at the [User Input](../guide/user-input.html) page and the [Event binding](../guide/template-syntax.html#event-binding) section of the [Template Syntax](../guide/template-syntax.html) page. :marked ### Add a click handler to expose the selected hero You no longer need the `hero` property because you're no longer displaying a single hero; you're displaying a list of heroes. But the user will be able to select one of the heroes by clicking on it. So replace the `hero` property with this simple `selectedHero` property: +makeExample('toh-2/ts/src/app/app.component.ts', 'selected-hero', 'src/app/app.component.ts (selectedHero)') :marked The hero names should all be unselected before the user picks a hero, so you won't initialize the `selectedHero` as you did with `hero`. Add an `onSelect` method that sets the `selectedHero` property to the `hero` that the user clicks. +makeExample('toh-2/ts/src/app/app.component.ts', 'on-select', 'src/app/app.component.ts (onSelect)')(format='.') :marked The template still refers to the old `hero` property. Bind to the new selectedHero property instead as follows: +makeExample('toh-2/ts/app/app.component.1.html', 'selectedHero-details', 'app.component.ts (template excerpt)')(format='.') :marked ### Hide the empty detail with ngIf When the app loads, the `selectedHero` is undefined and won't be defined until you click a hero's name. Angular can't display properties of the undefined `selectedHero` and throws the following error, visible in the browser's console: code-example(format="nocode"). EXCEPTION: TypeError: Cannot read property 'name' of undefined in [null] :marked Although `selectedHero.name` is displayed in the template, you must keep the hero detail out of the DOM until there is a selected hero. Wrap the HTML hero detail content of the template with a `
    `. Then add the `ngIf` built-in directive and set it to the `selectedHero` property of the component. +makeExample('toh-2/ts/app/app.component.1.html', 'ng-if', 'src/app/app.component.ts (ngIf)')(format='.') .alert.is-critical :marked Don't forget the asterisk (`*`) in front of `ngIf`. :marked The app no longer fails and the list of names displays again in the browser. :marked When there is no `selectedHero`, the `ngIf` directive removes the hero detail HTML from the DOM. There are no hero detail elements or bindings to worry about. When the user picks a hero, `selectedHero` becomes defined and `ngIf` puts the hero detail content into the DOM and evaluates the nested bindings. .l-sub-section :marked Read more about `ngIf` and `ngFor` in the [Structural Directives](../guide/structural-directives.html) page and the [Built-in directives](../guide/template-syntax.html#directives) section of the [Template Syntax](../guide/template-syntax.html) page. :marked ### Style the selected hero While the selected hero details appear below the list, it's difficult to identify the selected hero within the list itself. In the `styles` metadata that you added above, there is a custom CSS class named `selected`. To make the selected hero more visible, you'll apply this `selected` class to the `
  • ` when the user clicks on a hero name. For example, when the user clicks "Magneta", it should render with a distinctive but subtle background color like this: figure.image-display img(src='/resources/images/devguide/toh/heroes-list-selected.png' alt="Selected hero") :marked In the template, add the following `[class.selected]` binding to the `
  • `: +makeExample('toh-2/ts/app/app.component.1.html', 'class-selected-1', 'app.component.ts (setting the CSS class)')(format=".") :marked When the expression (`hero === selectedHero`) is `true`, Angular adds the `selected` CSS class. When the expression is `false`, Angular removes the `selected` class. .l-sub-section :marked Read more about the `[class]` binding in the [Template Syntax](../guide/template-syntax.html#ngClass "Template syntax: NgClass") guide. :marked The final version of the `
  • ` looks like this: +makeExample('toh-2/ts/app/app.component.1.html', 'class-selected-2', 'app.component.ts (styling each hero)')(format=".") :marked After clicking "Magneta", the list should look like this: figure.image-display img(src='/resources/images/devguide/toh/heroes-list-1.png' alt="Output of heroes list app") :marked Here's the complete `app.component.ts` as of now: +makeExample('toh-2/ts/src/app/app.component.ts', '', 'src/app/app.component.ts') .l-main-section :marked ## The road you've travelled Here's what you achieved in this page: * The Tour of Heroes app displays a list of selectable heroes. * You added the ability to select a hero and show the hero's details. * You learned how to use the built-in directives `ngIf` and `ngFor` in a component's template. Your app should look like this . ## The road ahead You've expanded the Tour of Heroes app, but it's far from complete. You can't put the entire app into a single component. In the [next page](toh-pt3.html), you'll split the app into sub-components and make them work together.