# 1. The hero editor

The application now has a basic title. Next, create a new component to display hero information and place that component in the application shell.

> For the sample application that this page describes, see the [live example](https://v17.angular.io/generated/live-examples/toh-pt1/stackblitz.html) / [download example](https://v17.angular.io/generated/zips/toh-pt1/toh-pt1.zip).

## Create the heroes component <a href="#create-the-heroes-component" id="create-the-heroes-component"></a>

Use `ng generate` to create a new component named `heroes`.

```
ng generate component heroes
```

`ng generate` creates a new directory , `src/app/heroes/`, and generates the three files of the `HeroesComponent` along with a test file.

The `HeroesComponent` class file is as follows:

{% tabs %}
{% tab title="app/heroes/heroes.component.ts (initial version)" %}

```typescript
import { Component } from '@angular/core';

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css'],
})
export class HeroesComponent {
}
```

{% endtab %}
{% endtabs %}

You always import the `Component` symbol from the Angular core library and annotate the component class with `@Component`.

`@Component` is a decorator function that specifies the Angular metadata for the component.

`ng generate` created three metadata properties:

| PROPERTIES    | DETAILS                                             |
| ------------- | --------------------------------------------------- |
| `selector`    | The component's CSS element selector.               |
| `templateUrl` | The location of the component's template file.      |
| `styleUrls`   | The location of the component's private CSS styles. |

The [CSS element selector](https://developer.mozilla.org/docs/Web/CSS/Type_selectors), `'app-heroes'`, matches the name of the HTML element that identifies this component within a parent component's template.

Always `export` the component class so you can `import` it elsewhere … like in the `AppModule`.

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

Add a `hero` property to the `HeroesComponent` for a hero named, `Windstorm`.

{% tabs %}
{% tab title="heroes.component.ts (hero property)" %}

```typescript
hero = 'Windstorm';
```

{% endtab %}
{% endtabs %}

### Show the hero <a href="#show-the-hero" id="show-the-hero"></a>

Open the `heroes.component.html` template file. Delete the default text that `ng generate` created and replace it with a data binding to the new `hero` property.

{% tabs %}
{% tab title="heroes.component.html" %}

```html
<h2>{{hero}}</h2>
```

{% endtab %}
{% endtabs %}

## Show the `HeroesComponent` view <a href="#show-the-heroescomponent-view" id="show-the-heroescomponent-view"></a>

To display the `HeroesComponent`, you must add it to the template of the shell `AppComponent`.

Remember that `app-heroes` is the element selector for the `HeroesComponent`. Add an `<app-heroes>` element to the `AppComponent` template file, just below the title.

{% tabs %}
{% tab title="src/app/app.component.html" %}

```html
<h1>{{title}}</h1>
<app-heroes></app-heroes>
```

{% endtab %}
{% endtabs %}

If `ng serve` is still running, the browser should refresh and display both the application title and the hero's name.

<figure><img src="/files/VGeR38aLpsNRk4JSqrOq" alt="" width="117"><figcaption></figcaption></figure>

Tipp von Jason:

> Wenn du wie von uns vorgeschlagen Webstorm als IDE verwendest, können Module mit den folgenden Tastenkürzel einfach importiert werden.
>
> Windows / Linux: `Alt + Enter`
>
> Mac: `Option + Enter`

## Create a `Hero` interface <a href="#create-a-hero-interface" id="create-a-hero-interface"></a>

A real hero is more than a name.

Create a `Hero` interface in its own file in the `src/app` directory . Give it `id` and `name` properties.

{% tabs %}
{% tab title="src/app/hero.ts" %}

```typescript
export interface Hero {
  id: number;
  name: string;
}
```

{% endtab %}
{% endtabs %}

Return to the `HeroesComponent` class and import the `Hero` interface.

Refactor the component's `hero` property to be of type `Hero`. Initialize it with an `id` of `1` and the name `Windstorm`.

The revised `HeroesComponent` class file should look like this:

{% tabs %}
{% tab title="src/app/heroes/heroes.component.ts" %}

```typescript
import {  } from '@angular/core';
import { Hero } from '../hero';

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css'],
  standalone: true,
})
export class HeroesComponent {
  hero: Hero = {
    id: 1,
    name: 'Windstorm'
  };
}
```

{% endtab %}
{% endtabs %}

The page no longer displays properly because you changed the hero from a string to an object.

## Show the hero object <a href="#show-the-hero-object" id="show-the-hero-object"></a>

Update the binding in the template to announce the hero's name and show both `id` and `name` in a details display like this:

{% tabs %}
{% tab title="heroes.component.html (HeroesComponent template)" %}

```html
<h2>{{hero.name}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div><span>name: </span>{{hero.name}}</div>
```

{% endtab %}
{% endtabs %}

The browser refreshes and displays the hero's information.

## Format with the `UppercasePipe` <a href="#format-with-the-uppercasepipe" id="format-with-the-uppercasepipe"></a>

Edit the `hero.name` binding like this:

{% tabs %}
{% tab title="src/app/heroes/heroes.component.html" %}

```html
<h2>{{hero.name | uppercase}} Details</h2>
```

{% endtab %}
{% endtabs %}

The browser refreshes and now the hero's name is displayed in capital letters.

The word [`uppercase`](https://v17.angular.io/api/common/UpperCasePipe) in the interpolation binding after the pipe `|` character, activates the built-in `UppercasePipe`.

[Pipes](https://v17.angular.io/guide/pipes-overview) are a good way to format strings, currency amounts, dates, and other display data. Angular ships with several built-in pipes, and you can create your own.

## Edit the hero <a href="#edit-the-hero" id="edit-the-hero"></a>

Users should be able to edit the hero's name in an `<input>` text box.

The text box should both *display* the hero's `name` property and *update* that property as the user types. That means data flows from the component class *out to the screen* and from the screen *back to the class*.

To automate that data flow, set up a two-way data binding between the `<input>` form element and the `hero.name` property.

### Two-way binding <a href="#two-way-binding" id="two-way-binding"></a>

Refactor the details area in the `HeroesComponent` template so it looks like this:

{% tabs %}
{% tab title="src/app/heroes/heroes.component.html (HeroesComponent's template)" %}

```html
<div>
  <label for="name">Hero name: </label>
  <input id="name" [(ngModel)]="hero.name" placeholder="name">
</div>
```

{% endtab %}
{% endtabs %}

`[(`[`ngModel`](https://v17.angular.io/api/forms/NgModel)`)]` is Angular's two-way data binding syntax.

Here it binds the `hero.name` property to the HTML text box so that data can flow *in both directions*. Data can flow from the `hero.name` property to the text box and from the text box back to the `hero.name`.

#### The missing [`FormsModule`](https://v17.angular.io/api/forms/FormsModule) <a href="#the-missing-formsmodule" id="the-missing-formsmodule"></a>

Notice that the application stopped working when you added `[(`[`ngModel`](https://v17.angular.io/api/forms/NgModel)`)]`.

To see the error, open the browser development tools and look in the console for a message like

```
Template parse errors:
Can't bind to 'ngModel' since it isn't a known property of 'input'.
```

Although [`ngModel`](https://v17.angular.io/api/forms/NgModel) is a valid Angular directive, it isn't available by default.

It belongs to the optional [`FormsModule`](https://v17.angular.io/api/forms/FormsModule) and you must *opt in* to using it.

{% tabs %}
{% tab title=" src/app/heroes/heroes.component.ts" %}

```typescript
import { Component } from '@angular/core';
import { Hero } from '../hero';
import { FormsModule } from '@angular/forms'; // <-- NgModel lives here


@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css'],
  standalone: true,
  imports: [
    BrowserModule,
    FormsModule, // <-- Import the forms module
  ],
})
export class HeroesComponent {
  // ...
}
```

{% endtab %}
{% endtabs %}

## Final code review <a href="#final-code-review" id="final-code-review"></a>

Here are the code files discussed on this page.

{% tabs %}
{% tab title=" src/app/heroes/heroes.component.ts" %}

```typescript
import { Component } from '@angular/core';
import { Hero } from '../hero';

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css'],
  standalone: true,
  imports: [
    BrowserModule,
    FormsModule,
  ],
})
export class HeroesComponent {
  hero: Hero = {
    id: 1,
    name: 'Windstorm'
  };
}
```

{% endtab %}

{% tab title="src/app/heroes/heroes.component.html" %}

```html
<h2>{{hero.name | uppercase}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div>
  <label for="name">Hero name: </label>
  <input id="name" [(ngModel)]="hero.name" placeholder="name">
</div>
```

{% endtab %}

{% tab title="src/app/app.component.ts" %}

```typescript
@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss'],
    standalone: true,
    imports: [RouterLink, RouterOutlet, MessagesComponent]
})
export class AppComponent {
  title = 'Tour of Heroes';
}
```

{% endtab %}

{% tab title="src/app.app.component.html" %}

```html
<h1>{{title}}</h1>
<app-heroes></app-heroes>
```

{% endtab %}

{% tab title="src/app/hero.ts" %}

```typescript
export interface Hero {
  id: number;
  name: string;
}
```

{% endtab %}
{% endtabs %}

## Summary <a href="#summary" id="summary"></a>

* You used `ng generate` to create a second `HeroesComponent`.
* You displayed the `HeroesComponent` by adding it to the `AppComponent` shell.
* You applied the `UppercasePipe` to format the name.
* You used two-way data binding with the [`ngModel`](https://v17.angular.io/api/forms/NgModel) directive.
* You learned about the `AppModule`.
* You imported the [`FormsModule`](https://v17.angular.io/api/forms/FormsModule) in the `AppModule` so that Angular would recognize and apply the [`ngModel`](https://v17.angular.io/api/forms/NgModel) directive.
* You learned the importance of declaring components in the `AppModule`.

## -> Hier geht es weiter

{% content-ref url="/pages/XtrwCjRwMyWg08sUPoO4" %}
[Hinweise und Zusatzaufgaben zu Kapitel 1](/tag-1/tour-of-heroes/1.-the-hero-editor/hinweise-und-zusatzaufgaben-zu-kapitel-1.md)
{% endcontent-ref %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://m335.ict-bz.ch/tag-1/tour-of-heroes/1.-the-hero-editor.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
