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 <live-example></live-example>.

.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 `<li>` 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 `<li>` 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 `<li>` 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 `<li>` like this:


  +makeExample('toh-2/ts/app/app.component.1.html', 'selectedHero-click', 'app.component.ts (template excerpt)')(format='.')

  :marked
    The parentheses identify the `<li>` 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 `<div>`.
    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 `<li>` 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 `<li>`:
  +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 `<li>` 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 <live-example></live-example>.

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