# 3. Create a feature component

At the moment, the `HeroesComponent` displays both the list of heroes and the selected hero's details.

Keeping all features in one component as the application grows won't be maintainable. This tutorial splits up large components into smaller subcomponents, each focused on a specific task or workflow.

The first step is to move the hero details into a separate, reusable `HeroDetailComponent` and end up with:

* A `HeroesComponent` that presents the list of heroes.
* A `HeroDetailComponent` that presents the details of a selected hero.

## Make the `HeroDetailComponent`

Use this `ng generate` command to create a new component named `hero-detail`.

```bash
ng generate component hero-detail
```

The command scaffolds the following:

* Creates a directory `src/app/hero-detail`.

Inside that directory, four files are created:

* A SCSS file for the component styles.
* An HTML file for the component template.
* A TypeScript file with a component class named `HeroDetailComponent`.
* A test file for the `HeroDetailComponent` class.

#### Write the template <a href="#write-the-template" id="write-the-template"></a>

Cut the HTML for the hero detail from the bottom of the `HeroesComponent` template and paste it over the boilerplate content in the `HeroDetailComponent` template.

The pasted HTML refers to a `selectedHero`. The new `HeroDetailComponent` can present _any_ hero, not just a selected hero. Replace `selectedHero` with `hero` everywhere in the template.

When you're done, the `HeroDetailComponent` template should look like this:

{% tabs %}
{% tab title="src/app/hero-detail/hero-detail.component.html" %}
```html
@if (hero(); as hero) {
  <div>
    <h2>{{hero.name | uppercase}} Details</h2>
    <div><span>id: </span>{{hero.id}}</div>
    <div>
      <label for="hero-name">Hero name: </label>
      <input id="hero-name" [(ngModel)]="hero.name" placeholder="name">
    </div>
  </div>
}
```
{% endtab %}
{% endtabs %}

## Add the input hero property <a href="#add-the-input-hero-property" id="add-the-input-hero-property"></a>

The `HeroDetailComponent` template binds to the component's `hero` property which is of type `Hero`.

Open the `HeroDetailComponent` class file and import the `Hero` symbol.

{% tabs %}
{% tab title="  src/app/hero-detail/hero-detail.component.ts (import Hero)" %}
```typescript
import { Hero } from '../hero';
```
{% endtab %}
{% endtabs %}

The `hero` property [input signal](https://angular.dev/guide/components/inputs), because the _external_ `HeroesComponent` [binds to it](https://v16.angular.io/tutorial/tour-of-heroes/toh-pt3#heroes-component-template) like this.

```html
<app-hero-detail [hero]="selectedHero" />
```

Amend the `@angular/core` import statement to include the [`input`](https://angular.dev/api/core/input) symbol.

{% tabs %}
{% tab title="src/app/hero-detail/hero-detail.component.ts (import Input)" %}
```typescript
import { Component, input } from '@angular/core';
```
{% endtab %}
{% endtabs %}

Add a `hero` property, preceded by the [`input`](https://angular.dev/api/core/input) function.

{% tabs %}
{% tab title="src/app/hero-detail/hero-detail.component.ts" %}
```typescript
hero = input<Hero>();
```
{% endtab %}
{% endtabs %}

That's the only change you should make to the `HeroDetailComponent` class. There are no more properties. There's no presentation logic. This component only receives a hero object through its `hero` property and displays it.

## Show the `HeroDetailComponent` <a href="#show-the-herodetailcomponent" id="show-the-herodetailcomponent"></a>

The `HeroesComponent` used to display the hero details on its own, before you removed that part of the template. This section guides you through delegating logic to the `HeroDetailComponent`.

The two components have a parent/child relationship. The parent, `HeroesComponent`, controls the child, `HeroDetailComponent` by sending it a new hero to display whenever the user selects a hero from the list.

You don't need to change the `HeroesComponent` _class_, instead change its _template_.

### Update the `HeroesComponent` template <a href="#update-the-heroescomponent-template" id="update-the-heroescomponent-template"></a>

The `HeroDetailComponent` selector is `'app-hero-detail'`. Add an `<app-hero-detail>` element near the bottom of the `HeroesComponent` template, where the hero detail view used to be.

Bind the `HeroesComponent.selectedHero` to the element's `hero` property like this.

{% tabs %}
{% tab title="heroes.component.html (HeroDetail binding)" %}
```html
<app-hero-detail [hero]="selectedHero" />
```
{% endtab %}
{% endtabs %}

`[hero]="selectedHero"` is an Angular [property binding](https://v16.angular.io/guide/property-binding).

It's a _one-way_ data binding from the `selectedHero` property of the `HeroesComponent` to the `hero` property of the target element, which maps to the `hero` property of the `HeroDetailComponent`.

Now when the user clicks a hero in the list, the `selectedHero` changes. When the `selectedHero` changes, the _property binding_ updates `hero` and the `HeroDetailComponent` displays the new hero.

The revised `HeroesComponent` template should look like this:

{% tabs %}
{% tab title="heroes.component.html" %}
```html
<h2>My Heroes</h2>
<ul class="heroes">
  @for (hero of heroes; track hero.id; let i = $index) {
    <li>
      <button [class.selected]="hero === selectedHero" type="button" (click)="onSelect(hero)">
        <span class="badge">{{hero.id}}</span>
        <span class="name">{{hero.name}}</span>
      </button>
    </li>
  }
</ul>

<app-hero-detail [hero]="selectedHero" />
```
{% endtab %}
{% endtabs %}

The browser refreshes and the application starts working again as it did before.

## What changed?

As before, whenever a user clicks on a hero name, the hero detail appears below the hero list. Now the `HeroDetailComponent` is presenting those details instead of the `HeroesComponent`.

Refactoring the original `HeroesComponent` into two components yields benefits, both now and in the future:

1. You reduced the `HeroesComponent` responsibilities.
2. You can evolve the `HeroDetailComponent` into a rich hero editor without touching the parent `HeroesComponent`.
3. You can evolve the `HeroesComponent` without touching the hero detail view.
4. You can re-use the `HeroDetailComponent` in the template of some future component.

## Final code review

Here are the code files discussed on this page.

{% tabs %}
{% tab title="src/app/hero-detail/hero-detail.component.ts" %}
```typescript
import { Component, input } from '@angular/core';
import { Hero } from '../hero';

@Component({
  selector: 'app-hero-detail',
  templateUrl: './hero-detail.component.html',
  styleUrls: ['./hero-detail.component.scss'],
  standalone: true
})
export class HeroDetailComponent {
  hero = input<Hero>();
}
```
{% endtab %}

{% tab title="src/app/hero-detail/hero-detail.component.html" %}
<pre class="language-html"><code class="lang-html">@if(hero(); as hero) {
<strong>  &#x3C;div>
</strong>    &#x3C;h2>{{hero.name | uppercase}} Details&#x3C;/h2>
    &#x3C;div>&#x3C;span>id: &#x3C;/span>{{hero.id}}&#x3C;/div>
    &#x3C;div>
      &#x3C;label for="hero-name">Hero name: &#x3C;/label>
      &#x3C;input id="hero-name" [(ngModel)]="hero.name" placeholder="name">
    &#x3C;/div>
  &#x3C;/div>
}
</code></pre>
{% endtab %}

{% tab title="src/app/heroes/heroes.component.html" %}
```html
<h2>My Heroes</h2>
<ul class="heroes">
  @for (hero of heroes; track hero.id; let i = $index) {
    <li>
      <button [class.selected]="hero === selectedHero" type="button" (click)="onSelect(hero)">
        <span class="badge">{{hero.id}}</span>
        <span class="name">{{hero.name}}</span>
      </button>
    </li>
  }
</ul>

<app-hero-detail [hero]="selectedHero" />
```
{% endtab %}
{% endtabs %}

## Summary

* You created a separate, reusable `HeroDetailComponent`.
* You used a [property binding](https://v16.angular.io/guide/property-binding) to give the parent `HeroesComponent` control over the child `HeroDetailComponent`.
* You used the [input](https://app.gitbook.com/s/ycEAGesbRhvLeca22hwC/) function to make the `hero` property available for binding by the external `HeroesComponent`.
