import {Component} from '@angular/core';
@Component({
	moduleId: module.id,
	selector: 'my-app',
	template: `
		<h1>{{title}}</h1>
		<nav>
			<a routerLink="/dashboard" routerLinkActive="active">ダッシュボード</a>
			<a routerLink="/heroines" routerLinkActive="active">ヒロインたち</a>
		</nav>
		<router-outlet></router-outlet>
		`,
	styleUrls: ['app.component.css']
})
export class AppComponent {
	title = 'ヒロイン一覧';
}
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {FormsModule} from '@angular/forms';
import {HttpModule} from '@angular/http';
import {InMemoryWebApiModule} from 'angular-in-memory-web-api';
import {InMemoryDataService} from './in-memory-data.service';
import {AppComponent} from './app.component';
import {HeroineDetailComponent} from './heroine-detail.component';
import {HeroinesComponent} from './heroines.component';
import {HeroineService} from './heroine.service';
import {DashboardComponent} from './dashboard.component';
import {AppRoutingModule} from './app-routing.module';
import {HeroineSearchComponent} from './heroine-search.component';
@NgModule({
	imports: [
		BrowserModule,
		FormsModule,
		HttpModule,
		InMemoryWebApiModule.forRoot(InMemoryDataService),
		AppRoutingModule
	],
	declarations: [
		AppComponent,
		DashboardComponent,
		HeroineDetailComponent,
		HeroinesComponent,
		HeroineSearchComponent
	],
	providers: [HeroineService],
	bootstrap: [AppComponent]
})
export class AppModule {}
h1 {
	color: #369;
	font-family: Arial, Helvetica, sans-serif;
	font-size: 250%;
}
h2, h3 {
	color: #444;
	font-family: Arial, Helvetica, sans-serif;
	font-weight: lighter;
}
body {
	margin: 2em;
}
body, input[text], button {
	color: #888;
	font-family: Cambria, Georgia;
}
a {
	cursor: pointer;
	cursor: hand;
}
button {
	font-family: Arial;
	background-color: #eee;
	border: none;
	padding: 5px 10px;
	border-radius: 4px;
	cursor: pointer;
	cursor: hand;
}
button:hover {
	background-color: #cfd8dc;
}
button:disabled {
	background-color: #eee;
	color: #aaa;
	cursor: auto;
}
nav a {
	padding: 5px 10px;
	text-decoration: none;
	margin-right: 10px;
	margin-top: 10px;
	display: inline-block;
	background-color: #eee;
	border-radius: 4px;
}
nav a:visited, a:link {
	color: #607D8B;
}
nav a:hover {
	color: #039be5;
	background-color: #CFD8DC;
}
nav a.active {
	color: #039be5;
}
.items {
	margin: 0 0 2em 0;
	list-style-type: none;
	padding: 0;
	width: 24em;
}
.items li {
	cursor: pointer;
	position: relative;
	left: 0;
	background-color: #EEE;
	margin: .5em;
	padding: .3em 0;
	height: 1.6em;
	border-radius: 4px;
}
.items li:hover {
	color: #607D8B;
	background-color: #DDD;
	left: .1em;
}
.items li.selected {
	background-color: #CFD8DC;
	color: white;
}
.items li.selected:hover {
	background-color: #BBD8DC;
}
.items .text {
	position: relative;
	top: -3px;
}
.items .badge {
	display: inline-block;
	font-size: small;
	color: white;
	padding: 0.8em 0.7em 0 0.7em;
	background-color: #607D8B;
	line-height: 1em;
	position: relative;
	left: -1px;
	top: -4px;
	height: 1.8em;
	margin-right: .8em;
	border-radius: 4px 0 0 4px;
}
* {
	font-family: Arial, Helvetica, sans-serif;
}
<html>
<head>
	<!-- <base href="/"> -->
  <script>document.write('<base href="' + document.location + '" />');</script>
	<title>Angular QuickStart</title>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<link rel="stylesheet" href="styles.css">
	<!-- 1. ライブラリの読み込み -->
	<!-- 古いブラウザへの対応 --><script src="https://unpkg.com/core-js/client/shim.min.js"></script>
	<script src="https://unpkg.com/zone.js@0.7.2?main=browser"></script>
	<script src="https://unpkg.com/reflect-metadata@0.1.8"></script>
	<script src="https://unpkg.com/systemjs@0.19.39/dist/system.src.js"></script>
	<!-- 2. SystemJSの設定 -->
	<!--<script src="systemjs.config.js"></script>-->
	<script src="https://cdn.rawgit.com/angular/angular.io/b3c65a9/public/docs/_examples/_boilerplate/systemjs.config.web.js"></script>
	<script>
		System.import('app').catch(function(err){ console.error(err); });
	</script>
</head>
<!-- 3. アプリケーションの表示 -->
<body>
	<my-app>Loading...</my-app>
</body>
</html>
export class Heroine {
	id: number;
	name: string;
}
import 'rxjs/add/operator/switchMap';
import {Component, Input, OnInit} from '@angular/core';
import {ActivatedRoute, Params} from '@angular/router';
import {Location} from '@angular/common';
import {Heroine} from './heroine';
import {HeroineService} from './heroine.service';
@Component({
	moduleId: module.id,
	selector: 'my-heroine-detail',
	templateUrl: 'heroine-detail.component.html',
	styleUrls: ['heroine-detail.component.css']
})
export class HeroineDetailComponent implements OnInit {
	@Input()
	heroine: Heroine;
	constructor(
		private heroineService: HeroineService,
		private route: ActivatedRoute,
		private location: Location
	) {}
	ngOnInit(): void {
		this.route.params
		.switchMap((params: Params) => this.heroineService.getHeroine(+params['id']))
		.subscribe((heroine: Heroine) => this.heroine = heroine);
	}
	goBack(): void {
		this.location.back();
	}
	save(): void {
		this.heroineService.update(this.heroine)
			.then(() => this.goBack());
	}
}
import {Heroine} from './heroine';
export const HEROINES: Heroine[] = [
	{ id: 11, name: 'シータ' },
	{ id: 12, name: 'ナウシカ' },
	{ id: 13, name: 'キキ' },
	{ id: 14, name: '千尋' },
	{ id: 15, name: 'さつき' },
	{ id: 16, name: 'ソフィー' },
	{ id: 17, name: 'マーニー' },
	{ id: 18, name: '菜穂子' },
	{ id: 19, name: 'サン' },
	{ id: 20, name: 'フィオ' }
];
import {Injectable} from '@angular/core';
import {Headers, Http, Response} from '@angular/http';
import 'rxjs/add/operator/toPromise';
import {Heroine} from './heroine';
@Injectable()
export class HeroineService {
	private headers: Headers = new Headers({'Content-Type': 'application/json'});
	private heroinesUrl: string = 'api/heroines';
	constructor(private http: Http) {}
	getHeroines(): Promise<Heroine[]> {
		return this.http.get(this.heroinesUrl)
			.toPromise()
			.then((response: Response) => response.json().data as Heroine[])
			.catch(this.handleError);
	}
	getHeroine(id: number): Promise<Heroine> {
		const url: string = `${this.heroinesUrl}/${id}`;
		return this.http.get(url)
			.toPromise()
			.then((response: Response) => response.json().data as Heroine)
			.catch(this.handleError);
	}
	create(name: string): Promise<Heroine> {
		return this.http
			.post(this.heroinesUrl, JSON.stringify({name: name}), {headers: this.headers})
			.toPromise()
			.then((response: Response) => response.json().data)
			.catch(this.handleError);
	}
	delete(id: number): Promise<void> {
		const url = `${this.heroinesUrl}/${id}`;
		return this.http.delete(url, {headers: this.headers})
			.toPromise()
			.then(() => null)
			.catch(this.handleError);
	}
	update(heroine: Heroine): Promise<Heroine> {
		const url: string = `${this.heroinesUrl}/${heroine.id}`;
		return this.http
			.put(url, JSON.stringify(heroine), {headers: this.headers})
			.toPromise()
			.then(() => heroine)
			.catch(this.handleError);
	}
	private handleError(error: any): Promise<any> {
		console.error('An error occured', error);
		return Promise.reject(error.message || error);
	}
}
h1 {
	font-size: 1.2em;
	color: #999;
	margin-bottom: 0;
}
h2 {
	font-size: 2em;
	margin-top: 0;
	padding-top: 0;
}
nav a {
	padding: 5px 10px;
	text-decoration: none;
	margin-top: 10px;
	display: inline-block;
	background-color: #eee;
	border-radius: 4px;
}
nav a:visited, a:link {
	color: #607D8B;
}
nav a:hover {
	color: #039be5;
	background-color: #CFD8DC;
}
nav a.active {
	color: #039be5;
}
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {HeroineDetailComponent} from './heroine-detail.component';
import {HeroinesComponent} from './heroines.component';
import {DashboardComponent} from './dashboard.component';
const routes: Routes = [
	{
		path: '',
		redirectTo: '/dashboard',
		pathMatch: 'full'
	},
	{
		path: 'dashboard',
		component: DashboardComponent
	},
	{
		path: 'heroines',
		component: HeroinesComponent
	},
	{
		path: 'detail/:id',
		component: HeroineDetailComponent
	}
];
@NgModule({
	imports: [
		RouterModule.forRoot(routes)
	],
	exports: [RouterModule]
})
export class AppRoutingModule {}
[class*='col-'] {
	float: left;
	padding-right: 20px;
	padding-bottom: 20px;
}
[class*='col-']:last-of-type {
	padding-right: 0;
}
a {
	text-decoration: none;
}
*, *:after, *:before {
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	box-sizing: border-box;
}
h3 {
	text-align: center; margin-bottom: 0;
}
h4 {
	position: relative;
}
.grid {
	margin: 0;
}
.col-1-4 {
	width: 25%;
}
.module {
	padding: 20px;
	text-align: center;
	color: #eee;
	max-height: 120px;
	min-width: 120px;
	background-color: #607D8B;
	border-radius: 2px;
}
.module:hover {
	background-color: #EEE;
	cursor: pointer;
	color: #607d8b;
}
.grid-pad {
	padding: 10px 0;
}
.grid-pad > [class*='col-']:last-of-type {
	padding-right: 20px;
}
@media (max-width: 600px) {
	.module {
		font-size: 10px;
		max-height: 75px;
	}
}
@media (max-width: 1024px) {
	.grid {
		margin: 0;
	}
	.module {
		min-width: 60px;
	}
}
<h3>トップヒロイン</h3>
<div class="grid grid-pad">
	<a *ngFor="let heroine of heroines" [routerLink]="['/detail', heroine.id]" class="col-1-4">
		<div class="module heroine">
			<h4>{{heroine.name}}</h4>
		</div>
	</a>
</div>
<heroine-search></heroine-search>
import {Component, OnInit} from '@angular/core';
import {Heroine} from './heroine';
import {HeroineService} from './heroine.service';
@Component({
	moduleId: module.id,
	selector: 'my-dashboard',
	templateUrl: 'dashboard.component.html',
	styleUrls: ['dashboard.component.css']
})
export class DashboardComponent implements OnInit {
	heroines: Heroine[];
	constructor(private heroineService: HeroineService) {}
	ngOnInit(): void {
		this.heroineService.getHeroines()
		.then((heroines: Heroine[]) => this.heroines = heroines.slice(0, 4));
	}
}
label {
	display: inline-block;
	width: 3em;
	margin: .5em 0;
	color: #607D8B;
	font-weight: bold;
}
input {
	height: 2em;
	font-size: 1em;
	padding-left: .4em;
}
button {
	margin-top: 20px;
	font-family: Arial;
	background-color: #eee;
	border: none;
	padding: 5px 10px;
	border-radius: 4px;
	cursor: pointer; cursor: hand;
}
button:hover {
	background-color: #cfd8dc;
}
button:disabled {
	background-color: #eee;
	color: #ccc; 
	cursor: auto;
}
<div *ngIf="heroine">
	<h2>{{heroine.name}}の情報</h2>
	<div><label>番号: </label>{{heroine.id}}</div>
	<div>
		<label>名前: </label>
		<input [(ngModel)]="heroine.name" placeholder="名前">
	</div>
	<button (click)="goBack()">戻る</button>
	<button (click)="save()">保存</button>
</div>
.selected {
	background-color: #CFD8DC !important;
	color: white;
}
.heroines {
	margin: 0 0 2em 0;
	list-style-type: none;
	padding: 0;
	width: 15em;
}
.heroines li {
	cursor: pointer;
	position: relative;
	left: 0;
	background-color: #EEE;
	margin: 0.5em;
	padding: 0.3em 0;
	height: 1.6em;
	border-radius: 4px;
}
.heroines li.selected:hover {
	background-color: #BBD8DC !important;
	color: white;
}
.heroines li:hover {
	color: #607D8B;
	background-color: #DDD;
	left: 0.1em;
}
.heroines .text {
	position: relative;
	top: -3px;
}
.heroines .badge {
	display: inline-block;
	font-size: small;
	color: white;
	padding: 0.8em 0.7em 0 0.7em;
	background-color: #607D8B;
	line-height: 1em;
	position: relative;
	left: -1px;
	top: -4px;
	height: 1.8em;
	margin-right: .8em;
	border-radius: 4px 0 0 4px;
}
button.delete {
  float:right;
  margin-top: 2px;
  margin-right: .8em;
  background-color: gray !important;
  color:white;
}
<h2>ヒロインたち</h2>
<div>
	<label>ヒロイン名:</label> <input #heroineName />
	<button (click)="add(heroineName.value); heroineName.value=''">
		追加
	</button>
</div>
<ul class="heroines">
	<li *ngFor="let heroine of heroines"
			[class.selected]="heroine === selectedHeroine"
			(click)="onSelect(heroine)">
		<span class="badge">{{heroine.id}}</span>
		<span>{{heroine.name}}</span>
		<button class="delete"
			(click)="delete(heroine); $event.stopPropagation()">x</button>
	</li>
</ul>
<div *ngIf="selectedHeroine">
	<h2>
		ヒロイン「{{selectedHeroine.name}}」
	</h2>
	<button (click)="gotoDetail()">詳細を見る</button>
</div>
import {Component, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {Heroine} from './heroine';
import {HeroineService} from './heroine.service';
@Component({
	moduleId: module.id,
	selector: 'my-heroines',
	templateUrl: 'heroines.component.html',
	styleUrls: ['heroines.component.css']
})
export class HeroinesComponent implements OnInit {
	heroines: Heroine[];
	selectedHeroine: Heroine;
	constructor(
		private router: Router,
		private heroineService: HeroineService
	) {}
	onSelect(heroine: Heroine): void {
		this.selectedHeroine = heroine;
	}
	getHeroines(): void {
		this.heroineService.getHeroines().then((heroines: Heroine[]) => this.heroines = heroines);
	}
	add(name: string): void {
		name = name.trim();
		if (!name) {return;}
		this.heroineService.create(name)
			.then((heroine: Heroine) => {
				this.heroines.push(heroine);
				this.selectedHeroine = null;
		});
	}
	delete(heroine: Heroine): void {
		this.heroineService
			.delete(heroine.id)
			.then(() => {
				this.heroines = this.heroines.filter((_heroine: Heroine) => _heroine !== heroine);
				if (this.selectedHeroine === heroine) {
					this.selectedHeroine = null;
				}
			});
	}
	ngOnInit(): void {
		this.getHeroines();
	}
	gotoDetail(): void {
		this.router.navigate(['/detail', this.selectedHeroine.id]);
	}
}
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app.module';
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);
import {InMemoryDbService} from 'angular-in-memory-web-api';
import {Heroine} from './heroine';
export class InMemoryDataService implements InMemoryDbService {
	createDb() {
		let heroines: Heroine[] = [
			{id: 11, name: 'シータ'},
			{id: 12, name: 'ナウシカ'},
			{id: 13, name: 'キキ'},
			{id: 14, name: '千尋'},
			{id: 15, name: 'さつき'},
			{id: 16, name: 'ソフィー'},
			{id: 17, name: 'マーニー'},
			{id: 18, name: '菜穂子'},
			{id: 19, name: 'サン'},
			{id: 20, name: 'フィオ'}
		];
		return {heroines};
	}
}
import {Injectable} from '@angular/core';
import {Http, Response} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import {Heroine} from './heroine';
@Injectable()
export class HeroineSearchService {
	constructor(private http: Http) {}
	search(term: string): Observable<Heroine[]> {
		return this.http
			.get(`app/heroines/?name=${term}`)
			.map((response: Response) => response.json().data as Heroine[]);
	}
}
<div id="search-component">
	<h4>ヒロイン検索</h4>
	<input #searchBox id="search-box" (keyup)="search(searchBox.value)" />
	<div>
		<div *ngFor="let heroine of heroines | async"
			(click)="gotoDetail(heroine)" class="search-result" >
			{{heroine.name}}
		</div>
	</div>
</div>
.search-result {
	border-bottom: 1px solid gray;
	border-left: 1px solid gray;
	border-right: 1px solid gray;
	width: 195px;
	height: 16px;
	padding: 5px;
	background-color: white;
	cursor: pointer;
}
.search-result:hover {
	color: #eee;
	background-color: #607D8B;
}
#search-box {
	width: 200px;
	height: 20px;
}
import {Component, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import {HeroineSearchService} from './heroine-search.service';
import {Heroine} from './heroine';
@Component({
	moduleId: module.id,  // [*1]
	selector: 'heroine-search',
	templateUrl: './heroine-search.component.html',
	styleUrls: ['./heroine-search.component.css'],
	providers: [HeroineSearchService]
})
export class HeroineSearchComponent implements OnInit {
	heroines: Observable<Heroine[]>;
	private searchTerms = new Subject<string>();
	constructor(
		private heroineSearchService: HeroineSearchService,
		private router: Router) {}
	search(term: string): void {
		this.searchTerms.next(term);
	}
	ngOnInit(): void {
		this.heroines = this.searchTerms
		.debounceTime(300)
		.distinctUntilChanged()
		.switchMap((term: string) => term
			? this.heroineSearchService.search(term)
			: Observable.of<Heroine[]>([]))
		.catch(error => {
			console.log(error);
			return Observable.of<Heroine[]>([]);
		});
	}
	gotoDetail(heroine: Heroine): void {
		let link = ['/detail', heroine.id];
		this.router.navigate(link);
	}
}