18
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Angular 5公式Tutorialの作例を改善する

Last updated at Posted at 2018-02-15

Angularの公式Tutorialは、全体をとおしてひとつの作例「Angular Example - Tour of Heroes: Part 6 」をつくります。この解説を下じきに、もっと細かくコードの動きが確かめられるように、説明の仕方やサンプルも改めて「Angular 5入門」を書きました。そのとき、公式の作例にいくつか気づいて直した点があります。それらをご紹介しましょう。

要らないコードを除く

「Routing」の「Remove dead code (optional)」は、書き直しの結果要らなくなったコードを除いています。これに加えてもうひとつ削った方がよいのは、HeroDetailComponentクラスのデコレータ関数Input()です。

import { Component, OnInit, Input } from '@angular/core';

export class HeroDetailComponent implements OnInit {
	@Input() hero: Hero;

}

コンポーネントの詳細情報(hero-detail.component)をリスト表示(heroes.component)から分け、選択されたデータをサービスから得るようにしたからです。親だったリスト表示のコンポーネントから参照を得るためにプロパティ(hero)に添えていたデコレータ関数Input()は意味がなくなります。

import { Component, OnInit} from '@angular/core';

export class HeroDetailComponent implements OnInit {
	hero: Hero;

}

公式Tutorialにもこの修正が加えられそうです(「refactor(aio): refining code of tutorial 7 routing」)。

リストを空にするとデータが加えられない

まず、リスト表示の画面ですべての項目を削除します(図001)。

図001■リスト項目がなくなった

1802001_001.png

つぎに、新たな項目をテキストフィールドに入力して、[add]ボタンを押します(図002)。

図002■新たな項目を入力する

1802001_002.png

すると、番号もテキストも空の項目が加えられます(図003)。ブラウザのコンソールを確かめると、つぎのようなエラーが示されました。

body: {error: "Collection 'heroes' id type is non-numeric or unknown. Can only generate numeric ids."}

図003■番号とテキストが空の項目

1802001_003.png

データの配列が空になって、プロパティidをもつオブジェクトがなくなると、新たな番号はつくれず、データも加えられないようです。

HttpClient.put()メソッドを使えば、データにid番号を定めて追加できます。リストが空のときは、つぎのようにidは初期値にしてHttpClient.put()メソッドでデータを送ればよいでしょう。

export class HeroService {

	// addHero(hero: Hero): Observable<Hero> {
	addHero(hero: Hero, numHeros: number): Observable<Hero> {
		let heroOvserbable;
		// return this.http.post<Hero>(this.herosUrl, hero, httpOptions)
		if (numHeros === 0) {
			hero.id = 11;
			heroOvserbable = this.http.put(this.herosUrl, hero, httpOptions)
		} else {
			heroOvserbable = this.http.post<Hero>(this.herosUrl, hero, httpOptions);
		}
		return heroOvserbable

	}

}

ただし、サービスのクラス(HeroService)はデータの配列を知りません。ですから、リスト表示クラス(HerosComponent)がデータ追加(add()メソッド)のためにサービス(HeroService)のメソッド(addHero())を呼び出すとき、第2引数としてデータ(heros)の長さ(Array.lengthプロパティ)を渡します。

export class HerosComponent implements OnInit {

	add(name: string): void {

		// this.heroService.addHero({name} as Hero)
		this.heroService.addHero({name} as Hero, this.heros.length)

	}

}

これで、リストを空にしても新たな項目が加えられます。これらの手直しをした作例は「Angular Example - Tour of Heroes: Part 6 revised」に掲げました。

Angular in-memory-web-apiモジュールのメソッドをオーバーライドする

リストを空にすると新たな項目がつくれないのは、Angular in-memory-web-api moduleの仕様にもとづくようです。デフォルトのid番号を返すBackendService.genIdDefault()メソッドは、BackendService.isCollectionIdNumeric()メソッドで、リストのデータがあり、さらに数値のidプロパティをもつかどうか確かめます。そうでなければ、デフォルトのid番号はできず、エラーになるのです。

データにid番号を振るのはBackendService.genId()メソッドです。このメソッドは、InMemoryDataServiceクラス(in-memory-data.service)でオーバーライドできます(「Tutorial example has a problem to enter new item into an empty list」参照)。すると、前項のようにサービス(HeroService)やリスト表示(HerosComponent)のクラスは書き替えずに済むのです。

InMemoryDataServiceクラスに定めてオーバーライドするつぎのgenId()メソッドは、データがあればid番号の最大値 + 1、なければ初期値を返します。この作例は"Angular Example - Tour of Heroes: Part 6"に掲げられています。

export class InMemoryDataService implements InMemoryDbService {

	genId(heroines: Heroine[]): number {
		return heroines.length > 0 ? Math.max(...heroines.map(heroine => heroine.id)) + 1 : 11;
	}
}

おまけ

細かいところで、もうひとつつけ加えておきます。サービスのクラス(HeroService)の検索メソッド(searchHeroes())で、URLを直書きしているところです。もとのパスはプロパティ(heroesUrl)に定めてあります。後あとの修正も考えるなら、プロパティを用いるべきでしょう。

export class HeroService {

	searchHeroes(term: string): Observable<Hero[]> {

		const url = `${this.heroesUrl}/?name=${term}`;
		// return this.http.get<Hero[]>(`api/heroes/?name=${term}`)
		return this.http.get<Hero[]>(url)

	}

}
18
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?