chore(toh): change inputs array for input decorator/hero now a class
This commit is contained in:
parent
10877bdbfc
commit
5f73911eaf
|
@ -1,4 +1,4 @@
|
|||
export interface Hero {
|
||||
export class Hero {
|
||||
name: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// #docregion pt1
|
||||
import {Component} from 'angular2/core';
|
||||
|
||||
// #docregion hero-interface-1
|
||||
interface Hero {
|
||||
// #docregion hero-class-1
|
||||
export class Hero {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
// #enddocregion hero-interface-1
|
||||
// #enddocregion hero-class-1
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// #docregion pt2
|
||||
import {Component} from 'angular2/core';
|
||||
|
||||
interface Hero {
|
||||
export class Hero {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ interface Hero {
|
|||
margin: 0 0 2em 0;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
width: 10em;
|
||||
width: 15em;
|
||||
}
|
||||
.heroes li {
|
||||
cursor: pointer;
|
||||
|
|
|
@ -32,7 +32,7 @@ import {HeroDetailComponent} from './hero-detail.component';
|
|||
margin: 0 0 2em 0;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
width: 10em;
|
||||
width: 15em;
|
||||
}
|
||||
.heroes li {
|
||||
cursor: pointer;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// #docplaster
|
||||
// #docregion
|
||||
// #docregion v1
|
||||
import {Component} from 'angular2/core';
|
||||
import {Component, Input} from 'angular2/core';
|
||||
|
||||
// #enddocregion v1
|
||||
// #docregion hero-import
|
||||
import {Hero} from './hero';
|
||||
|
@ -10,7 +11,7 @@ import {Hero} from './hero';
|
|||
// #docregion v1
|
||||
@Component({
|
||||
selector: 'my-hero-detail',
|
||||
// #enddocregion v1
|
||||
// #enddocregion v1
|
||||
// #docregion template
|
||||
template: `
|
||||
<div *ngIf="hero">
|
||||
|
@ -21,18 +22,18 @@ import {Hero} from './hero';
|
|||
<input [(ngModel)]="hero.name" placeholder="name"/>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
`
|
||||
// #enddocregion template
|
||||
// #docregion inputs
|
||||
inputs: ['hero']
|
||||
// #enddocregion inputs
|
||||
// #docregion v1
|
||||
// #docregion v1
|
||||
})
|
||||
export class HeroDetailComponent {
|
||||
// #enddocregion v1
|
||||
// #docregion hero
|
||||
// #docregion hero-input
|
||||
@Input()
|
||||
// #docregion hero
|
||||
hero: Hero;
|
||||
// #enddocregion hero
|
||||
// #enddocregion hero
|
||||
// #enddocregion hero-input
|
||||
// #docregion v1
|
||||
}
|
||||
// #enddocregion v1
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// #docregion
|
||||
export interface Hero {
|
||||
export class Hero {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import {HeroService} from './hero.service';
|
|||
margin: 0 0 2em 0;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
width: 10em;
|
||||
width: 15em;
|
||||
}
|
||||
.heroes li {
|
||||
cursor: pointer;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// #docregion
|
||||
import {Component} from 'angular2/core';
|
||||
import {Component, Input} from 'angular2/core';
|
||||
import {Hero} from './hero';
|
||||
|
||||
@Component({
|
||||
|
@ -15,9 +15,8 @@ import {Hero} from './hero';
|
|||
<input [(ngModel)]="hero.name" placeholder="name"/>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
inputs: ['hero']
|
||||
`
|
||||
})
|
||||
export class HeroDetailComponent {
|
||||
hero: Hero;
|
||||
@Input() hero: Hero;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export interface Hero {
|
||||
export class Hero {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
// #docregion
|
||||
// #docregion v2
|
||||
// #docregion import-oninit
|
||||
import { Component, OnInit } from 'angular2/core';
|
||||
import { Component, Input, OnInit } from 'angular2/core';
|
||||
// #enddocregion import-oninit
|
||||
// #docregion import-route-params
|
||||
import {RouteParams} from 'angular2/router';
|
||||
import { RouteParams } from 'angular2/router';
|
||||
// #enddocregion import-route-params
|
||||
|
||||
import { Hero } from './hero';
|
||||
|
@ -20,15 +20,14 @@ import { HeroService } from './hero.service';
|
|||
templateUrl: 'app/hero-detail.component.html',
|
||||
// #enddocregion template-url
|
||||
// #enddocregion v2
|
||||
styleUrls: ['app/hero-detail.component.css'],
|
||||
inputs: ['hero']
|
||||
styleUrls: ['app/hero-detail.component.css']
|
||||
// #docregion v2
|
||||
})
|
||||
// #enddocregion extract-template
|
||||
// #docregion implement
|
||||
export class HeroDetailComponent implements OnInit {
|
||||
// #enddocregion implement
|
||||
hero: Hero;
|
||||
@Input() hero: Hero;
|
||||
|
||||
// #docregion ctor
|
||||
constructor(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export interface Hero {
|
||||
export class Hero {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
margin: 0 0 2em 0;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
width: 10em;
|
||||
width: 15em;
|
||||
}
|
||||
.heroes li {
|
||||
cursor: pointer;
|
||||
|
|
|
@ -26,5 +26,5 @@ import {HeroService} from './hero.service';
|
|||
{path: '/detail/:id', name: 'HeroDetail', component: HeroDetailComponent}
|
||||
])
|
||||
export class AppComponent {
|
||||
public title = 'Tour of Heroes';
|
||||
title = 'Tour of Heroes';
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import {HeroService} from './hero.service';
|
|||
styleUrls: ['app/dashboard.component.css']
|
||||
})
|
||||
export class DashboardComponent implements OnInit {
|
||||
public heroes: Hero[] = [];
|
||||
heroes: Hero[] = [];
|
||||
|
||||
constructor(private _heroService: HeroService, private _router: Router) { }
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {Component, OnInit} from 'angular2/core';
|
||||
import {Component, Input, OnInit} from 'angular2/core';
|
||||
import {RouteParams} from 'angular2/router';
|
||||
|
||||
import {Hero} from './hero';
|
||||
|
@ -7,11 +7,10 @@ import {HeroService} from './hero.service';
|
|||
@Component({
|
||||
selector: 'my-hero-detail',
|
||||
templateUrl: 'app/hero-detail.component.html',
|
||||
styleUrls: ['app/hero-detail.component.css'],
|
||||
inputs: ['hero']
|
||||
styleUrls: ['app/hero-detail.component.css']
|
||||
})
|
||||
export class HeroDetailComponent implements OnInit {
|
||||
public hero: Hero;
|
||||
@Input() hero: Hero;
|
||||
|
||||
constructor(private _heroService: HeroService,
|
||||
private _routeParams: RouteParams) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export interface Hero {
|
||||
export class Hero {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
margin: 0 0 2em 0;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
width: 10em;
|
||||
width: 15em;
|
||||
}
|
||||
.heroes li {
|
||||
cursor: pointer;
|
||||
|
|
|
@ -11,8 +11,8 @@ import {Hero} from './hero';
|
|||
directives: [HeroDetailComponent]
|
||||
})
|
||||
export class HeroesComponent implements OnInit {
|
||||
public heroes: Hero[];
|
||||
public selectedHero: Hero;
|
||||
heroes: Hero[];
|
||||
selectedHero: Hero;
|
||||
|
||||
constructor(private _heroService: HeroService, private _router: Router) { }
|
||||
|
||||
|
|
|
@ -66,31 +66,15 @@ code-example(format="" language="bash").
|
|||
### Hero object
|
||||
|
||||
At the moment, our hero is just a name. Our hero needs more properties.
|
||||
Let's convert the `hero` from a literal string to an interface.
|
||||
Let's convert the `hero` from a literal string to a class.
|
||||
|
||||
Create a `Hero` interface with `id` and `name` properties.
|
||||
Create a `Hero` class with `id` and `name` properties.
|
||||
For now put this near the top of the `app.component.ts` file, just below the import statement.
|
||||
|
||||
+makeExample('toh-1/ts/app/app.component.ts', 'hero-interface-1', 'app.component.ts (Hero interface)')(format=".")
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
#### Interface or Class?
|
||||
Why a `Hero` interface and not a `Hero` class?
|
||||
We want a strongly typed `Hero`. We get strong typing with either option.
|
||||
Our choice depends on how we intend to use the `Hero`.
|
||||
|
||||
If we need a `Hero` that goes beyond simple properties, a `Hero` with logic and behavior,
|
||||
we must define a class.
|
||||
If we only need type checking, the interface is sufficient and lighter weight.
|
||||
|
||||
Lighter weight? Transpiling a class to JavaScript produces code.
|
||||
Transpiling an interface produces — nothing.
|
||||
If the class does nothing (and there is nothing for a `Hero` class to do right now),
|
||||
we prefer an interface.
|
||||
+makeExample('toh-1/ts/app/app.component.ts', 'hero-class-1', 'app.component.ts (Hero class)')(format=".")
|
||||
|
||||
:marked
|
||||
Now that we have a `Hero` interface, let’s refactor our component’s `hero` property to be of type `Hero`.
|
||||
Now that we have a `Hero` class, let’s refactor our component’s `hero` property to be of type `Hero`.
|
||||
Then initialize it with an id of `1` and the name, "Windstorm".
|
||||
|
||||
+makeExample('toh-1/ts-snippets/app.component.snippets.pt1.ts', 'hero-property-1', 'app.component.ts (Hero property)')(format=".")
|
||||
|
|
|
@ -51,13 +51,13 @@ code-example(format="." language="bash").
|
|||
+makeExample('toh-2/ts/app/app.component.ts', 'hero-array', 'app.component.ts (Hero array)')
|
||||
|
||||
:marked
|
||||
The `HEROES` array is of type `Hero`, the interface defined in part one,
|
||||
The `HEROES` array is of type `Hero`, the class defined in part one,
|
||||
to create an array of heroes.
|
||||
We aspire to fetch this list of heroes from a web service, but let’s take small steps
|
||||
first and display mock heroes.
|
||||
|
||||
### Exposing heroes
|
||||
Let’s create a public property in `AppComponent` that exposes the heroes for binding.
|
||||
Let’s create a property in `AppComponent` that exposes the heroes for binding.
|
||||
|
||||
+makeExample('toh-2/ts-snippets/app.component.snippets.pt2.ts', 'hero-array-1', 'app.component.ts (Hero array property)')
|
||||
|
||||
|
|
|
@ -73,14 +73,13 @@ code-example(format="." language="bash").
|
|||
:marked
|
||||
-->
|
||||
:marked
|
||||
We begin by importing the `Component` function from Angular so that we have it handy when we create
|
||||
the metadata for our component.
|
||||
|
||||
We begin by importing the `Component` and `Input` decorators from Angular because we're going to need them soon.
|
||||
|
||||
We create metadata with the `@Component` decorator where we
|
||||
specify the selector name that identifies this component's element.
|
||||
Then we export the class to make it available to other components.
|
||||
|
||||
When we finish here, we'll import it into `AppComponent` and refer to its `<my-hero-detail>` element.
|
||||
When we finish here, we'll import it into `AppComponent` and create a corresponding `<my-hero-detail>` element.
|
||||
:marked
|
||||
#### Hero Detail Template
|
||||
At the moment, the *Heroes* and *Hero Detail* views are combined in one template in `AppComponent`.
|
||||
|
@ -100,18 +99,18 @@ code-example(format="." language="bash").
|
|||
Let’s add that `hero` property we were talking about to the component class.
|
||||
+makeExample('toh-3/ts/app/hero-detail.component.ts', 'hero')
|
||||
:marked
|
||||
Uh oh. We declared the `hero` property as type `Hero` but our `Hero` interface is over in the `app.component.ts` file.
|
||||
We have two components, each in their own file, that need to reference the `Hero` interface.
|
||||
Uh oh. We declared the `hero` property as type `Hero` but our `Hero` class is over in the `app.component.ts` file.
|
||||
We have two components, each in their own file, that need to reference the `Hero` class.
|
||||
|
||||
We solve the problem by relocating the `Hero` interface from `app.component.ts` to its own `hero.ts` file.
|
||||
We solve the problem by relocating the `Hero` class from `app.component.ts` to its own `hero.ts` file.
|
||||
|
||||
+makeExample('toh-3/ts/app/hero.ts', null, 'hero.ts (Exported Hero interface)')(format=".")
|
||||
+makeExample('toh-3/ts/app/hero.ts', null, 'hero.ts (Exported Hero class)')(format=".")
|
||||
|
||||
:marked
|
||||
We export the `Hero` interface from `hero.ts` because we'll need to reference it in both component files.
|
||||
We export the `Hero` class from `hero.ts` because we'll need to reference it in both component files.
|
||||
Add the following import statement near the top of both `app.component.ts` and `hero-detail.component.ts`.
|
||||
|
||||
+makeExample('toh-3/ts/app/hero-detail.component.ts', 'hero-import', 'hero-detail.component.ts and app.component.ts (Import the Hero interface)')
|
||||
+makeExample('toh-3/ts/app/hero-detail.component.ts', 'hero-import', 'hero-detail.component.ts and app.component.ts (Import the Hero class)')
|
||||
|
||||
:marked
|
||||
#### The *hero* property is an ***input***
|
||||
|
@ -137,14 +136,13 @@ code-example(format=".").
|
|||
*source* properties do not.
|
||||
:marked
|
||||
There are a couple of ways we can declare that `hero` is an *input*.
|
||||
We'll do it by adding an `inputs` array to the `@Component` metadata.
|
||||
+makeExample('toh-3/ts/app/hero-detail.component.ts', 'inputs')
|
||||
We'll do it the way we *prefer*, by annotating the `hero` property with the `@Input` decorator that we imported earlier.
|
||||
+makeExample('toh-3/ts/app/hero-detail.component.ts', 'hero-input')(format='.')
|
||||
|
||||
.l-sub-section
|
||||
:marked
|
||||
Learn about the `@Input()` decorator way in the
|
||||
Learn more about the `@Input()` decorator in the
|
||||
[Attribute Directives](../guide/attribute-directives.html#input) chapter.
|
||||
:marked
|
||||
|
||||
.l-main-section
|
||||
:marked
|
||||
|
|
|
@ -113,7 +113,7 @@ code-example(format="." language="bash").
|
|||
We'll move the mock data to its own file.
|
||||
|
||||
Cut the `HEROES` array from `app.component.ts` and paste it to a new file in the `app` folder named `mock-heroes.ts`.
|
||||
We copy the `import {Hero} ...` statement as well because the heroes array uses the `Hero` interface.
|
||||
We copy the `import {Hero} ...` statement as well because the heroes array uses the `Hero` class.
|
||||
|
||||
+makeExample('toh-4/ts/app/mock-heroes.ts', null, 'mock-heroes.ts (Heroes array)')
|
||||
:marked
|
||||
|
|
Loading…
Reference in New Issue