Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@ import { HEROES } from '../mock-heroes';
styleUrls: ['./heroes.component.css']
})
// #enddocregion metadata

// #docregion component
export class HeroesComponent implements OnInit {

// #docregion heroes
heroes = HEROES;
// #enddocregion heroes

// #enddocregion component
// #docregion on-select
selectedHero: Hero;

// #enddocregion on-select
// #enddocregion on-select

constructor() { }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ <h3>Top Heroes</h3>
<!-- #docregion click -->
<a *ngFor="let hero of heroes" class="col-1-4"
routerLink="/detail/{{hero.id}}">
<!-- #enddocregion click -->
<div class="module hero">
<h4>{{hero.name}}</h4>
</div>
</a>
<!-- #enddocregion click -->
</div>
10 changes: 10 additions & 0 deletions aio/content/examples/toh-pt6/src/app/in-memory-data.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// #docregion , init
import { InMemoryDbService } from 'angular-in-memory-web-api';
import { Hero } from './hero';

export class InMemoryDataService implements InMemoryDbService {
createDb() {
Expand All @@ -17,4 +18,13 @@ export class InMemoryDataService implements InMemoryDbService {
];
return {heroes};
}

// Overrides the genId method to ensure that a hero always has an id.
// If the heroes array is empty,
// the method below returns the initial number (11).
// if the heroes array is not empty, the method below returns the highest
// hero id + 1.
genId(heroes: Hero[]): number {
return heroes.length > 0 ? Math.max(...heroes.map(hero => hero.id)) + 1 : 11;
}
}
5 changes: 3 additions & 2 deletions aio/content/tutorial/toh-pt2.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ Open the `HeroesComponent` class file and import the mock `HEROES`.
<code-example path="toh-pt2/src/app/heroes/heroes.component.ts" region="import-heroes" title="src/app/heroes/heroes.component.ts (import HEROES)">
</code-example>

Add a `heroes` property to the class that exposes these heroes for binding.
In the same file (`HeroesComponent` class), define a component property called `heroes` to expose `HEROES` array for binding.

<code-example path="toh-pt2/src/app/heroes/heroes.component.ts" region="heroes">
<code-example path="toh-pt2/src/app/heroes/heroes.component.ts" region="component">
</code-example>

### List heroes with _*ngFor_
Expand Down Expand Up @@ -245,6 +245,7 @@ Here are the code files discussed on this page, including the `HeroesComponent`

<code-pane title="src/app/heroes/heroes.component.css" path="toh-pt2/src/app/heroes/heroes.component.css">
</code-pane>

</code-tabs>

## Summary
Expand Down
30 changes: 21 additions & 9 deletions aio/content/tutorial/toh-pt3.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Master/Detail Components

At the moment, the `HeroesComponent` displays both the list of heroes and the selected hero's details.
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 will not be maintainable.
You'll want to split up large components into smaller sub-components, each focused on a specific task or workflow.
Expand All @@ -18,15 +18,27 @@ Use the Angular CLI to generate a new component named `hero-detail`.
ng generate component hero-detail
</code-example>

The command scaffolds the `HeroDetailComponent` files and declares the component in `AppModule`.
The command scaffolds the following:

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

Inside that directory four files are generated:

* A CSS 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.

The command also adds the `HeroDetailComponent` as a declaration in the `@NgModule` decorator of the `src/app/app.module.ts` file.


### Write the template

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

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

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

Expand All @@ -41,11 +53,11 @@ which is of type `Hero`.

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

<code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.ts"
<code-example path="toh-pt3/src/app/hero-detail/hero-detail.component.ts"
region="import-hero" title="src/app/hero-detail/hero-detail.component.ts (import Hero)">
</code-example>

The `hero` property
The `hero` property
[must be an _Input_ property](guide/template-syntax#inputs-outputs "Input and Output properties"),
annotated with the `@Input()` decorator,
because the _external_ `HeroesComponent` [will bind to it](#heroes-component-template) like this.
Expand All @@ -64,17 +76,17 @@ Add a `hero` property, preceded by the `@Input()` decorator.
</code-example>

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

## Show the `HeroDetailComponent`

The `HeroesComponent` is still a master/detail view.
The `HeroesComponent` is still a master/detail view.

It used to display the hero details on its own, before you cut that portion of the template. Now it will delegate to the `HeroDetailComponent`.

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

Expand Down Expand Up @@ -155,6 +167,6 @@ Here are the code files discussed on this page and your app should look like thi
* You used a [property binding](guide/template-syntax#property-binding) to give the parent `HeroesComponent` control over the child `HeroDetailComponent`.


* You used the [`@Input` decorator](guide/template-syntax#inputs-outputs)
* You used the [`@Input` decorator](guide/template-syntax#inputs-outputs)
to make the `hero` property available for binding
by the external `HeroesComponent`.
23 changes: 19 additions & 4 deletions aio/content/tutorial/toh-pt6.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ which you will create in a moment.
</code-example>

Add the `HttpClientInMemoryWebApiModule` to the `@NgModule.imports` array&mdash;
_after importing the `HttpClient`_,
_after importing the `HttpClientModule`_,
&mdash;while configuring it with the `InMemoryDataService`.

<code-example
Expand Down Expand Up @@ -114,7 +114,9 @@ you'll wrap it in private `log` method.
region="log" >
</code-example>

Define the `heroesUrl` with the address of the heroes resource on the server.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Earlier in the file on line 61, it says Add the HttpClientInMemoryWebApiModule to the @NgModule.imports array— after importing the HttpClient

HttpClient should be HttpClientModule

Define the `heroesUrl` of the form `:base/:collectionName` with the address of the heroes resource on the server.
Here `base` is the resource to which requests are made,
and `collectionName` is the heroes data object in the `in-memory-data-service.ts`.

<code-example
path="toh-pt6/src/app/hero.service.ts"
Expand Down Expand Up @@ -242,8 +244,11 @@ Here is the final version of `getHeroes` with the `tap` that logs the operation.

### Get hero by id

Most web APIs support a _get by id_ request in the form `api/hero/:id`
(such as `api/hero/11`).
Most web APIs support a _get by id_ request in the form `:baseURL/:id`.

Here, the _base URL_ is the `heroesURL` defined in the [Heroes and HTTP](http://localhost:4800/tutorial/toh-pt6#heroes-and-http) section (`api/heroes`) and _id_ is
the number of the hero that you want to retrieve. For example, `api/heroes/11`.

Add a `HeroService.getHero()` method to make that request:

<code-example path="toh-pt6/src/app/hero.service.ts" region="getHero" title="src/app/hero.service.ts"></code-example>
Expand Down Expand Up @@ -629,6 +634,16 @@ Here are the code files discussed on this page (all in the `src/app/` folder).
</code-pane>
</code-tabs>

{@a dashboardcomponent}
#### _DashboardComponent_

<code-tabs>
<code-pane
title="src/app/dashboard/dashboard.component.html"
path="toh-pt6/src/app/dashboard/dashboard.component.html">
</code-pane>
</code-tabs>

{@a herosearchcomponent}
#### _HeroSearchComponent_

Expand Down