parent
6a62ed2245
commit
c7e2930f25
|
@ -12,16 +12,17 @@ import { HEROES } from '../mock-heroes';
|
||||||
styleUrls: ['./heroes.component.css']
|
styleUrls: ['./heroes.component.css']
|
||||||
})
|
})
|
||||||
// #enddocregion metadata
|
// #enddocregion metadata
|
||||||
|
|
||||||
|
// #docregion component
|
||||||
export class HeroesComponent implements OnInit {
|
export class HeroesComponent implements OnInit {
|
||||||
|
|
||||||
// #docregion heroes
|
// #docregion heroes
|
||||||
heroes = HEROES;
|
heroes = HEROES;
|
||||||
// #enddocregion heroes
|
// #enddocregion heroes
|
||||||
|
// #enddocregion component
|
||||||
// #docregion on-select
|
// #docregion on-select
|
||||||
selectedHero: Hero;
|
selectedHero: Hero;
|
||||||
|
// #enddocregion on-select
|
||||||
// #enddocregion on-select
|
|
||||||
|
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
<!-- #docregion click -->
|
<!-- #docregion click -->
|
||||||
<a *ngFor="let hero of heroes" class="col-1-4"
|
<a *ngFor="let hero of heroes" class="col-1-4"
|
||||||
routerLink="/detail/{{hero.id}}">
|
routerLink="/detail/{{hero.id}}">
|
||||||
<!-- #enddocregion click -->
|
|
||||||
<div class="module hero">
|
<div class="module hero">
|
||||||
<h4>{{hero.name}}</h4>
|
<h4>{{hero.name}}</h4>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
<!-- #enddocregion click -->
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// #docregion , init
|
// #docregion , init
|
||||||
import { InMemoryDbService } from 'angular-in-memory-web-api';
|
import { InMemoryDbService } from 'angular-in-memory-web-api';
|
||||||
|
import { Hero } from './hero';
|
||||||
|
|
||||||
export class InMemoryDataService implements InMemoryDbService {
|
export class InMemoryDataService implements InMemoryDbService {
|
||||||
createDb() {
|
createDb() {
|
||||||
|
@ -17,4 +18,13 @@ export class InMemoryDataService implements InMemoryDbService {
|
||||||
];
|
];
|
||||||
return {heroes};
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 path="toh-pt2/src/app/heroes/heroes.component.ts" region="import-heroes" title="src/app/heroes/heroes.component.ts (import HEROES)">
|
||||||
</code-example>
|
</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>
|
</code-example>
|
||||||
|
|
||||||
### List heroes with _*ngFor_
|
### List heroes with _*ngFor_
|
||||||
|
@ -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 title="src/app/heroes/heroes.component.css" path="toh-pt2/src/app/heroes/heroes.component.css">
|
||||||
</code-pane>
|
</code-pane>
|
||||||
|
|
||||||
</code-tabs>
|
</code-tabs>
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Master/Detail Components
|
# 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.
|
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.
|
You'll want to split up large components into smaller sub-components, each focused on a specific task or workflow.
|
||||||
|
@ -18,7 +18,19 @@ Use the Angular CLI to generate a new component named `hero-detail`.
|
||||||
ng generate component hero-detail
|
ng generate component hero-detail
|
||||||
</code-example>
|
</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
|
### Write the template
|
||||||
|
|
||||||
|
@ -26,7 +38,7 @@ Cut the HTML for the hero detail from the bottom of the `HeroesComponent` templa
|
||||||
|
|
||||||
The pasted HTML refers to a `selectedHero`.
|
The pasted HTML refers to a `selectedHero`.
|
||||||
The new `HeroDetailComponent` can present _any_ hero, not just a selected hero.
|
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:
|
When you're done, the `HeroDetailComponent` template should look like this:
|
||||||
|
|
||||||
|
@ -41,11 +53,11 @@ which is of type `Hero`.
|
||||||
|
|
||||||
Open the `HeroDetailComponent` class file and import the `Hero` symbol.
|
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)">
|
region="import-hero" title="src/app/hero-detail/hero-detail.component.ts (import Hero)">
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The `hero` property
|
The `hero` property
|
||||||
[must be an _Input_ property](guide/template-syntax#inputs-outputs "Input and Output properties"),
|
[must be an _Input_ property](guide/template-syntax#inputs-outputs "Input and Output properties"),
|
||||||
annotated with the `@Input()` decorator,
|
annotated with the `@Input()` decorator,
|
||||||
because the _external_ `HeroesComponent` [will bind to it](#heroes-component-template) like this.
|
because the _external_ `HeroesComponent` [will bind to it](#heroes-component-template) like this.
|
||||||
|
@ -64,17 +76,17 @@ Add a `hero` property, preceded by the `@Input()` decorator.
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
That's the only change you should make to the `HeroDetailComponent` class.
|
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.
|
This component simply receives a hero object through its `hero` property and displays it.
|
||||||
|
|
||||||
## Show the `HeroDetailComponent`
|
## 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`.
|
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 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
|
by sending it a new hero to display whenever
|
||||||
the user selects a hero from the list.
|
the user selects a hero from the list.
|
||||||
|
|
||||||
|
@ -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 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
|
to make the `hero` property available for binding
|
||||||
by the external `HeroesComponent`.
|
by the external `HeroesComponent`.
|
||||||
|
|
|
@ -66,7 +66,7 @@ which you will create in a moment.
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Add the `HttpClientInMemoryWebApiModule` to the `@NgModule.imports` array—
|
Add the `HttpClientInMemoryWebApiModule` to the `@NgModule.imports` array—
|
||||||
_after importing the `HttpClient`_,
|
_after importing the `HttpClientModule`_,
|
||||||
—while configuring it with the `InMemoryDataService`.
|
—while configuring it with the `InMemoryDataService`.
|
||||||
|
|
||||||
<code-example
|
<code-example
|
||||||
|
@ -114,7 +114,9 @@ you'll wrap it in private `log` method.
|
||||||
region="log" >
|
region="log" >
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Define the `heroesUrl` with the address of the heroes resource on the server.
|
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
|
<code-example
|
||||||
path="toh-pt6/src/app/hero.service.ts"
|
path="toh-pt6/src/app/hero.service.ts"
|
||||||
|
@ -242,8 +244,11 @@ Here is the final version of `getHeroes` with the `tap` that logs the operation.
|
||||||
|
|
||||||
### Get hero by id
|
### Get hero by id
|
||||||
|
|
||||||
Most web APIs support a _get by id_ request in the form `api/hero/:id`
|
Most web APIs support a _get by id_ request in the form `:baseURL/:id`.
|
||||||
(such as `api/hero/11`).
|
|
||||||
|
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:
|
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>
|
<code-example path="toh-pt6/src/app/hero.service.ts" region="getHero" title="src/app/hero.service.ts"></code-example>
|
||||||
|
@ -629,6 +634,16 @@ Here are the code files discussed on this page (all in the `src/app/` folder).
|
||||||
</code-pane>
|
</code-pane>
|
||||||
</code-tabs>
|
</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}
|
{@a herosearchcomponent}
|
||||||
#### _HeroSearchComponent_
|
#### _HeroSearchComponent_
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue