include ../../../../_includes/_util-fns

.l-main-section
  :markdown
    # It Takes Many Heroes    
    Our story needs more heroes. 
    We’ll expand our Tour of Heroes app to display a list of heroes, 
    allow the user to select a hero, and display the hero’s details. 
    
    Let’s take stock of what we’ll need to display a list of heroes. 
    First, we need a list of heroes. We want to display those heroes in the view’s template, 
    so we’ll need a way to do that.
     
.l-main-section
  :markdown
    ## Where We Left Off
    Before we continue with Part 2 of the Tour of Heroes, 
    let’s verify we have the following structure after [Part 1](./toh-pt1.html).
    If not, we’ll need to go back to Part 1 and figure out what we missed.
    
  code-example.
      angular2-tour-of-heroes
        ├── node_modules
        ├── src
        |    ├── app
        |    |    └── app.ts
        |    ├── index.html
        |    └── tsconfig.json
        └── package.json 
  :markdown
    ### Keep the app running
    Start the TypeScript compiler and have it watch for changes in one terminal window by typing

  pre.prettyprint.lang-bash
    code npm run tsc

  :markdown
    Now open another terminal window and start the server by typing

  pre.prettyprint.lang-bash
    code npm start

  :markdown
    This will keep the application running while we continue to build the Tour of Heroes.

.l-main-section
  :markdown
    ## Displaying Our Heroes
    ### Creating heroes
    Let’s create an array of ten heroes at the bottom of `app.ts`.
    ```
    var HEROES: Hero[] = [
      { "id": 11, "name": "Mr. Nice" },
      { "id": 12, "name": "Narco" },
      { "id": 13, "name": "Bombasto" },
      { "id": 14, "name": "Celeritas" },
      { "id": 15, "name": "Magneta" },
      { "id": 16, "name": "RubberMan" },
      { "id": 17, "name": "Dynama" },
      { "id": 18, "name": "Dr IQ" },
      { "id": 19, "name": "Magma" },
      { "id": 20, "name": "Tornado" }
    ];
    ```
    The `HEROES` array is of type `Hero`. 
    We are taking advantage of the `Hero` class we coded previously to create an array of our heroes.  
    We aspire to get this list of heroes from a web service, but let’s take small steps 
    on this road and start by displaying these mock heroes in the browser.
     
    ### Exposing heroes
    Let’s create a public property in `AppComponent` that exposes the heroes for binding.
    ```
    public heroes = HEROES;
    ```
    We did not have to define the `heroes` type.  TypeScript can infer it from the `HEROES` array.
  .l-sub-section
    :markdown
      We could have defined the heroes list here in this component class. 
      But we know that we’ll get the heroes from a data service. 
      Because we know where we are heading, it makes sense to separate the hero data 
      from the class implementation from the start.
  :markdown
    ### Displaying heroes in a template
    Our component has`heroes`. Let’s create an unordered list in our template to display them. 
    We’ll insert the following chunk of HTML below the title and above the hero details.
     ```
    <h2>My Heroes</h2>
    <ul class="heroes">
      <li>
        <!-- each hero goes here -->
      </li>
    </ul>
    ```
    Now we have a template that we can fill with our heroes.

    ### Listing heroes with ng-for
    
    We want to bind the array of `heroes` in our component to our template, iterate over them, 
    and display them individually. 
    We’ll need some help from Angular to do this. Let’s do this step by step.
    
    First modify the `<li>` tag by adding the built-in directive `*ng-for`. 
    ```
    <li *ng-for="#hero of heroes">
    ```
  .alert.is-critical
    :markdown
      The leading asterisk (`*`) in front of `ng-for` is a critical part of this syntax.
      
  .l-sub-section
    :markdown
      The (`*`) prefix to `ng-for` indicates that the `<li>` element and its children
      constitute a master template.
      
      The `ng-for` directive iterates over the `heroes` array returned by the `AppComponent.heroes` property
      and stamps out instances of this template.
                  
      The quoted text assigned to `ng-for` means 
      “*take each hero in the `heroes` array, store it in the local `hero` variable,
      and make it available to the corresponding template instance*”.
  
      The `#` prefix before "hero" identifies the `hero` as a local template variable. 
      We can reference this variable within the template to access a hero’s properties.

      Learn more about `ng-for` and local template variables in the 
      [Template Syntax](../guide/template-syntax.html#ng-for) chapter.

  :markdown
    With this background in mind, we now insert some content between the `<li>` tags 
    that uses the `hero` template variable to display the hero’s properties.

  code-example(format="linenums" language="html").
    &lt;li *ng-for="#hero of heroes">
      &lt;span class="badge">{{hero.id}}&lt;/span> {{hero.name}}&lt;/a>
    &lt;/li>
    
  :markdown
    ### Declaring ng-for
    When we view the running app in the browser we see nothing … no heroes. 
    We open the developer tools and see an error in the console.
    
  code-example(language="html" ).
    EXCEPTION: 
    Can't bind to 'ngForOf' since it isn't a known property of the '&lt;template>' element and 
    there are no matching directives with a corresponding property

  :markdown
    Thankfully we have a clear error message that indicates where we went wrong. 
    We used `ng-for` in the template but we didn’t tell the component about it. 
    From Angular's perspective, `ng-for` is a meaningless attribute. 
    When it tries to render the view, it doesn’t recognize `ng-for` and gives up.
    
    We need to say “*hey component, I’m going to use this NgFor directive. OK?*”
    
    To that end, we first import  the `NgFor` symbol
    ```
    import {bootstrap, Component, FORM_DIRECTIVES, NgFor} from 'angular2/angular2';
    ```
    and then declare `NgFor` to be one of the view’s directives in the `@Component` decorator. 
    ```
    directives: [FORM_DIRECTIVES, NgFor]
    ```
    After the browser refreshes, we see a list of heroes!
    
    ### Styling our heroes
    Our list of heroes looks pretty bland.
    We want to make it visually obvious to a user which hero we are hovering over and which hero is selected.
    
    Let’s add some styles to our component by setting the `styles` property on the `@Component` decorator 
    to the following CSS classes:
    ```
    styles:[`
      .heroes {list-style-type: none; margin-left: 1em; padding: 0; width: 10em;}
      .heroes li { cursor: pointer; position: relative; left: 0; transition: all 0.2s ease; }
      .heroes li:hover {color: #369; background-color: #EEE; left: .2em;}
      .heroes .badge {
        font-size: small;
        color: white;
        padding: 0.1em 0.7em;
        background-color: #369;
        line-height: 1em;
        position: relative;
        left: -1px;
        top: -1px;
      }
      .selected { background-color: #EEE; color: #369; }
      `],
    ```
    Notice that we again use the back-tick notation for multi-line strings.
    
    When we assign styles to a component they are scoped to that specific component. 
    Our styles will only apply to our `AppComponent` and won't "leak" to the outer HTML.
    
    Our template for displaying the heroes should now look like this:
    
  code-example(format="linenums").    
    &lt;h2>My Heroes&lt;/h2>
    &lt;ul class="heroes">
      &lt;li *ng-for="#hero of heroes">
        &lt;span class="badge">{{hero.id}}&lt;/span> {{hero.name}}&lt;/a>
      &lt;/li>
    &lt;/ul>
  :markdown
    Our styled list of heroes should look like this:
 
  figure.image-display
    img(src='/resources/images/devguide/toh/heroes-list-2.png' alt="Output of heroes list app (no selection color)") 

.l-main-section
  :markdown
    ## Selecting a Hero
    We have a list of heroes and we have a single hero displayed in our app. 
    The list and the single hero are not connected in any way. 
    We want the user to select a hero from our list, and have the selected hero appear in the details view. 
    This UI pattern is widely known as “master-detail”. 
    In our case, the master is the heroes list and the detail is the selected hero. 
    
    Let’s connect the master to the detail through a `selectedHero` component property bound to a click event.
    
    ### Click event
    We modify the `<li>` by inserting an Angular event binding to its click event.
    
  code-example(format="linenums").   
    &lt;li *ng-for="#hero of heroes" (click)="onSelect(hero)">
      &lt;span class="badge">{{hero.id}}&lt;/span> {{hero.name}}&lt;/a>
    &lt;/li>
  :markdown
    Focus on the event binding
  pre.prettyprint.lang-bash
    code (click)="onSelect(hero)">
  :markdown
    The parenthesis identify the `<li>` element’s  `click` event as the target. 
    The expression to the right of the equal sign calls the  `AppComponent` method, `onSelect()`, 
    passing the local template variable `hero` as an argument.
    That’s the same `hero` variable we defined previously in the `ng-for`.
  .l-sub-section
    :markdown
      Learn more about Event Binding in the [Templating Syntax](../guide/template-syntax.html#event-binding) chapter.
  :markdown
    ### Add the click handler
    Our event binding refers to an `onSelect` method that doesn’t exist yet. 
    We’ll add that method to our component now. 
    
    What should that method do? It should set the component’s selected hero to the hero that the user clicked.
    
    Our component doesn’t have a “selected hero” yet either. We’ll start there.
    
    ### Expose the selected hero 
    We no longer need the static `hero` property of the `AppComponent`.
    **Replace** it with this simple `selectedHero` property:
    ```
    public selectedHero: Hero;
    ```
    We’ve decided that none of the heroes should be selected before the user picks a hero so 
    we won’t initialize the `selectedHero` as we were doing with `hero`. 
    
    Now **add an `onSelect` method** that sets the `selectedHero` property to the `hero` the user clicked.
    ```
    onSelect(hero: Hero) { this.selectedHero = hero; }
    ```
    
    We will be showing the selected hero's details in our template. 
    At the moment, it is still referring to the old `hero` property. 
    Let’s fix the template to bind to the new `selectedHero` property.
    
  code-example(format="linenums").    
    &lt;h2>{{selectedHero.name}} details!&lt;/h2>
    &lt;div>&lt;label>id: &lt;/label>{{selectedHero.id}}&lt;/div>
    &lt;div>
        &lt;label>name: &lt;/label>
        &lt;input [(ng-model)]="selectedHero.name" placeholder="name">&lt;/input>
    &lt;/div>
    
  :markdown
    ### Hide the empty detail with ng-if
    
    When our app loads we see a list of heroes, but a hero is not selected. 
    The `selectedHero` is `undefined`. 
    That’s why we'll see the following error in the browser’s console:
    
  code-example(language="html").
    EXCEPTION: TypeError: Cannot read property 'name' of undefined in [null]
    
  :markdown
    Remember that we are displaying `selectedHero.name` in the template. 
    This name property does not exist because `selectedHero`itself is undefined. 
    
    We'll address this problem by keeping the hero detail out of the DOM until there is a selected hero.
    
    We wrap the HTML hero detail content of our template with a `<div>`. 
    Then we add the `ng-if` built-in directive and set it to the `selectedHero` property of our component.
    
  code-example(format="linenums").
      &lt;div *ng-if="selectedHero">
        &lt;h2>{{selectedHero.name}} details!&lt;/h2>
        &lt;div>&lt;label>id: &lt;/label>{{selectedHero.id}}&lt;/div>
        &lt;div>
          &lt;label>name: &lt;/label>
          &lt;input [(ng-model)]="selectedHero.name" placeholder="name">&lt;/input>
        &lt;/div>
      &lt;/div>
  .alert.is-critical
    :markdown
      Remember that the leading asterisk (`*`) in front of `ng-if` is 
      a critical part of this syntax.
  :markdown
    When there is no `selectedHero`, the `ng-if` directive removes the hero detail HTML from the DOM. 
    There will no hero detail elements and no bindings to worry about. 
    
    When the user picks a hero, `selectedHero` becomes "truthy" and
    `ng-if` puts the hero detail content into the DOM and evaluates the nested bindings. 
  .l-sub-section
    :markdown
      `ng-if` and `ng-for` are called “structural directives” because they can change the 
      structure of portions of the DOM. 
      In other words, they give structure to the way Angular displays content in the DOM.
       
      Learn more about `ng-if`, `ng-for` and other structural directives in the 
      [Template Syntax](../guide/template-syntax.html#directives) chapter
    
  :markdown
    We learned previously with `NgFor` that we must declare every directive we use in the component’s `@Component` decorator. 
    Let’s do that again for `NgIf`.
    
    Add the `NgIf` symbol to our imports at the top of our `app.ts` file, keeping them sorted
    alphabetically to make them easier to find:
    ```
    import {bootstrap, Component, FORM_DIRECTIVES, NgFor, NgIf} from 'angular2/angular2';
    ```
  :markdown
    Now add `NgIf` to the directives array in the `@Component` decorator:
    ```
    directives: [FORM_DIRECTIVES, NgFor, NgIf]
    ```
    The browser refreshes and we see the list of heroes but not the selected hero detail. 
    The `ng-if` keeps it out of the DOM as long as the `selectedHero` is undefined. 
    When we click on a hero in the list, the selected hero displays in the hero details. 
    Everything is working as we expect.
     
    ### Styling the selection
    
    We see the selected hero in the details area below but we can’t quickly locate that hero in the list above. 
    We can fix that by applying the `selected` CSS class to the appropriate `<li>` in the master list. 
    For example, when we select Magneta from the heroes list, 
    we can make it pop out visually by giving it a subtle background color as shown here.
    
  figure.image-display
    img(src='/resources/images/devguide/toh/heroes-list-selected.png' alt="Selected hero")
  :markdown
    First we’ll add a `getSelectedClass` method to the component that compares the current `selectedHero` to a hero parameter 
    and returns an object with a single key/value pair. 
    
    The key is the name of the CSS class (`selected`). The value is `true` if the two heroes match and `false` otherwise. 
    We’re saying “*apply the `selected` class if the heroes match, remove it if they don’t*”. 
    Here is that method.
    ```
    getSelectedClass(hero: Hero) {
      return { 'selected': hero === this.selectedHero };
    }
    ```
    What do we do with this method and its peculiar result?
    
    ### ng-class
    We’ll add the `ng-class`built-in directive to the `<li>` element in our template and bind it to `getSelectedClass`.
    It’s no coincidence that the value returned by `getSelectedClass` is exactly what the `ng-class` requires 
    to add or remove the `selected` class to each hero’s display.
  code-example(format="linenums").     
      &lt;li *ng-for="#hero of heroes"
        [ng-class]="getSelectedClass(hero)"
        (click)="onSelect(hero)">
        &lt;span class="badge">{{hero.id}}&lt;/span> {{hero.name}}&lt;/a>
      &lt;/li>

  :markdown
    Notice in the template that the `ng-class` name is surrounded in square brackets (`[]`).  
    This is the syntax for a Property Binding, a binding in which data flows one way 
    from the data source (the `getSelectedClass`) to a property of the `ng-class` directive. 
 
  .l-sub-section
    :markdown
      Learn more about [ng-class](../guide/template-syntax.html#ng-class)
      and [Property Binding](../guide/template-syntax.html#property-binding) 
      in the Template Syntax chapter
  :markdown
    We've added yet another new directive to our template that we have to import and declare 
    in the component’s `directives` array as we’ve done twice before.
    ```
    import {bootstrap, Component, 
            FORM_DIRECTIVES, NgClass, NgFor, NgIf} from 'angular2/angular2';
    ```
    
    ```    
    directives: [FORM_DIRECTIVES, NgClass, NgFor, NgIf]
    ```
    The browser reloads our app. 
    We select a hero and the selection is clearly identified by the background color.
     
  figure.image-display
    img(src='/resources/images/devguide/toh/heroes-list-1.png' alt="Output of heroes list app")
    
  :markdown
    We select a different hero and the tell-tale color switches to that hero.
       
    ## Declaring Built-In Directives
    
    Every time we used a directive, we imported it and declared it in the component. 
    We only used three directives but we can easily envision a component that uses many more. 
    The `directives` array grows quickly and the process of importing the directive and adding it to the array is tedious. 
    We can make this easier.
    
    Remember how we imported the `FORM_DIRECTIVES` array to help us apply `ng-model`to our template in the previous chapter?
    The `FORM_DIRECTIVES` array held all the directives we needed for `ng-model` (and a few more). 
    We didn’t have to list them. We simply added the `FORM_DIRECTIVES` array to the component’s `directives` array.
    
    The `NgClass`, `NgFor`, and `NgIf` are extremely common directives used by many components in many applications. 
    Fortunately they are all exported from Angular as part of the `CORE_DIRECTIVES` array. 
    
    Let’s replace all of those separate import variables with `CORE_DIRECTIVES`:
    ```
    import {bootstrap, Component, CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/angular2';
    ```
    Then replace `NgClass`, `NgFor`, and `NgIf` in the `directives` array with `CORE_DIRECTIVES`:
    ```
    directives: [CORE_DIRECTIVES, FORM_DIRECTIVES]
    ```
    Everything still works and we have a convenient way to import and declare the most commonly used directives. 
    Cleaner code for the win!     
  
.l-main-section
  :markdown
    ## The Road We’ve Travelled
    Here’s what we achieved in this chapter:
    
    * Our Tour of Heroes now displays a list of selectable heroes 
    * We added the ability to select a hero and show the hero’s details
    * We learned how to use the built-in directives `ng-if`, `ng-for` and `ng-class` in a component’s template
     
    ### The Road Ahead
    Our Tour of Heroes has grown, but it’s far from complete. 
    We want to get data from an asynchronous source using promises, use shared services, and create reusable components. 
    We’ll learn more about these tasks in the coming tutorial chapters.
             