今回は、「HTTP」ですね。今回も間違ってる可能性大なので、お時間のある方のみご覧ください。一応、動いてはいますよ~。
The HttpModule
is not a core NgModule. HttpModule
is Angular's optional approach to web access. It exists as a separate add-on module called @angular/http
and is shipped in a separate script file as part of the Angular npm package.
You're ready to import from @angular/http
because systemjs.config
configured SystemJS to load that library when you need it.
「node_modules」>「@angular」>「http」がインストールされてれば利用できる状態になっているということのようです。
・FN1707005 | Angular 4入門 08: HTTPサービスでデータを取得・保存する | HTML5 : テクニカルノート
@ angular / httpライブラリのHttpModuleを使えるようにする
「app.module.ts」 ファイルに、「@angular/http」の「HttpModule」をインポートします。
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; // 追加 import { AppComponent } from './app.component'; import { DashboardComponent } from './dashboard.component'; import { HeroDetailComponent } from './hero-detail.component'; import { HeroesComponent } from './heroes.component'; import { HeroService } from './hero.service'; import { AppRoutingModule } from './app-routing.module'; @NgModule({ declarations: [ AppComponent, DashboardComponent, HeroDetailComponent, HeroesComponent ], imports: [ BrowserModule, FormsModule, AppRoutingModule, HttpModule // 追加 ], providers: [ HeroService ], bootstrap: [ AppComponent ] }) export class AppModule { }
Simulate the web APIを使う
本当は、どこかのサーバー上のWeb APIを利用するのが良いようですが、メモリで動くシミュレーションのモジュールangular-in-memory-web-apiを使っていくようです。
「app.module.ts」 ファイルに「angular-in-memory-web-api」とデータ用の「./in-memory-data.service」(後で作成の「in-memory-data.service.ts」)をインポートします。
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; // 追加 // Imports for loading & configuring the in-memory web api import { InMemoryWebApiModule } from 'angular-in-memory-web-api'; // 追加 import { InMemoryDataService } from './in-memory-data.service'; // 追加 import { AppComponent } from './app.component'; import { DashboardComponent } from './dashboard.component'; import { HeroDetailComponent } from './hero-detail.component'; import { HeroesComponent } from './heroes.component'; import { HeroService } from './hero.service'; import { AppRoutingModule } from './app-routing.module'; @NgModule({ declarations: [ AppComponent, DashboardComponent, HeroDetailComponent, HeroesComponent ], imports: [ BrowserModule, FormsModule, AppRoutingModule, HttpModule, // 追加 InMemoryWebApiModule.forRoot(InMemoryDataService), // 追加 AppRoutingModule ], providers: [ HeroService ], bootstrap: [ AppComponent ] }) export class AppModule { }
で、エラー。「Cannot find module 'angular-in-memory-web-api'」
よくエラーの出るチュートリアルですな。(自分のやり方が悪いんだとは思いますが、初心者に優しくないですな)
そも、チュートリアルとは?
これは、 「個別指導、家庭教師」 という意味です。 転じて、 「基本操作などを教えるプログラム」 という意味で使われます。 一番最初に操作方法などを説明するプログラム・教材等のことで、 「あなた一人に対して教育する(個別指導)」という意味で、 このチュートリアルという言葉が使われています。 主に基本操作や基礎的なものを教えるためのプログラムのことを言い、 動画や、実際の操作を伴っての説明が多いです。
「Angular DOC」は、スパルタ教師ですね....。
すみません、脱線いたしました。
⇧ 「package.json」に「angular2-in-memory-web-api": "0.0.21"」とかが普通は入ってるらしい。(いまは、「angular-in-memory-web-api」)
私の「C:¥workspace¥firstSpring¥src¥main¥resources¥static¥angular-tour-of-heroes¥package.json」ファイル、そもそもそんなもの存在しない。
{ "name": "angular-tour-of-heroes", "version": "0.0.0", "license": "MIT", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }, "private": true, "dependencies": { "@angular/animations": "^4.2.4", "@angular/common": "^4.2.4", "@angular/compiler": "^4.2.4", "@angular/core": "^4.2.4", "@angular/forms": "^4.2.4", "@angular/http": "^4.2.4", "@angular/platform-browser": "^4.2.4", "@angular/platform-browser-dynamic": "^4.2.4", "@angular/router": "^4.2.4", "core-js": "^2.4.1", "rxjs": "^5.4.2", "zone.js": "^0.8.14" }, "devDependencies": { "@angular/cli": "1.4.1", "@angular/compiler-cli": "^4.2.4", "@angular/language-service": "^4.2.4", "@types/jasmine": "~2.5.53", "@types/jasminewd2": "~2.0.2", "@types/node": "~6.0.60", "codelyzer": "~3.1.1", "jasmine-core": "~2.6.2", "jasmine-spec-reporter": "~4.1.0", "karma": "~1.7.0", "karma-chrome-launcher": "~2.1.1", "karma-cli": "~1.0.1", "karma-coverage-istanbul-reporter": "^1.2.1", "karma-jasmine": "~1.1.0", "karma-jasmine-html-reporter": "^0.2.2", "protractor": "~5.1.2", "ts-node": "~3.2.0", "tslint": "~5.3.2", "typescript": "~2.3.3" } }
チュートリアルにもインストールしろとかないんだけどな~....自分のような初心者には厳しきチュートリアルですな(涙)。
まぁ、とりあえず、「package.json」に「angular-in-memory-web-api」を追記していきますが、バージョンがどれていいか分からず(涙)。
・npm でパッケージのバージョン一覧を確認したりバージョンを指定してインストールしたりする方法 | phiary
⇧ npmの使い方は上記サイト様が詳しいです
npm info angular-in-memory-web-api versions
とりあえず、最新を入れてしまいますか...。
{ "name": "angular-tour-of-heroes", "version": "0.0.0", "license": "MIT", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }, "private": true, "dependencies": { "@angular/animations": "^4.2.4", "@angular/common": "^4.2.4", "@angular/compiler": "^4.2.4", "@angular/core": "^4.2.4", "@angular/forms": "^4.2.4", "@angular/http": "^4.2.4", "@angular/platform-browser": "^4.2.4", "@angular/platform-browser-dynamic": "^4.2.4", "@angular/router": "^4.2.4", "angular-in-memory-web-api": "^0.4.6", "core-js": "^2.4.1", "rxjs": "^5.4.2", "zone.js": "^0.8.14" }, "devDependencies": { "@angular/cli": "1.4.1", "@angular/compiler-cli": "^4.2.4", "@angular/language-service": "^4.2.4", "@types/jasmine": "~2.5.53", "@types/jasminewd2": "~2.0.2", "@types/node": "~6.0.60", "codelyzer": "~3.1.1", "jasmine-core": "~2.6.2", "jasmine-spec-reporter": "~4.1.0", "karma": "~1.7.0", "karma-chrome-launcher": "~2.1.1", "karma-cli": "~1.0.1", "karma-coverage-istanbul-reporter": "^1.2.1", "karma-jasmine": "~1.1.0", "karma-jasmine-html-reporter": "^0.2.2", "protractor": "~5.1.2", "ts-node": "~3.2.0", "tslint": "~5.3.2", "typescript": "~2.3.3" } }
そしたらば、コマンドプロンプトで「package.json」ファイルを持つプロジェクトに移動し(今回だと、「C:¥workspace¥firstSpring¥src¥main¥resources¥static¥angular-tour-of-heroes」)、
・npm で package.json がカレントディレクトリにない場合 - Please Sleep
⇧ 上記サイト様によるとフォルダ移動しなくてもいけるみたいです
npm install angular-in-memory-web-api@0.4.6
「C:¥workspace¥firstSpring¥src¥main¥resources¥static¥angular-tour-of-heroes¥node_modules」に「angular-in-memory-web-api」がインストールされました。
エラーも1つになり、ここのエラーは次の工程で「in-memory-data.service.ts」を作ればたぶん消えてくれるでしょう。
そんでは、「in-memory-data.service.ts」を作成します。「angular-tour-od-heroes」>「app」を選択した状態で右クリックし、「新規(W)」>「その他(O)...」をクリック。
「TypeScript」>「TypeScript Source File」を選択し、「次へ(N)>」をクリック。
「フォルダ名(F):」を「in-memory-data.service.ts」とし「完了(F)」。
「in-memory-data.service.ts」ファイルを編集。
import { InMemoryDbService } from 'angular-in-memory-web-api'; export class InMemoryDataService implements InMemoryDbService { createDb() { const heroes = [ { id: 0, name: 'Zero' }, { id: 11, name: 'Mr. Nice' }, { id: 12, name: 'Narco' }, { id: 13, name: 'Bombasto' }, { id: 14, name: 'Celeritas' }, { id: 15, name: 'Magneta' }, { id: 16, name: 'RubberMan' }, { id: 17, name: 'Dynama' }, { id: 18, name: 'Dr IQ' }, { id: 19, name: 'Magma' }, { id: 20, name: 'Tornado' } ]; return {heroes}; } }
保存すると、「app.module.ts」のエラーが消えました。
次に、「hero.service.ts」 を編集して、「mock-heroes.ts」ファイルから取得していたデータを、「in-memory-data.service.ts」ファイルから取得するように変更します。
import { Injectable } from '@angular/core'; import { Headers, Http } from '@angular/http'; import 'rxjs/add/operator/toPromise'; import { Hero } from './hero'; @Injectable() export class HeroService { private heroesUrl = 'api/heroes'; // URL to web api constructor(private http: Http) {} getHeroes(): Promise<Hero[]> { return this.http.get(this.heroesUrl) .toPromise() .then(response => response.json().data as Hero[]) .catch(this.handleError); } private handleError(error: any): Promise<any> { console.error('An error occurred', error); // for demo purposes only return Promise.reject(error.message || error); } getHero(id: number): Promise<hero> { return this.getHeroes() .then(heroes => heroes.find(hero => hero.id === id)); } }
ブラウザを更新してみると、「in-memory-data.service.ts」ファイルのデータが取得されています。
Updating hero details
同じく、「hero.service.ts」 のidで取得していたgetHero() メソッドも変更していきます。update()メソッドも追加します。
import { Injectable } from '@angular/core'; import { Headers, Http } from '@angular/http'; import 'rxjs/add/operator/toPromise'; import { Hero } from './hero'; @Injectable() export class HeroService { private heroesUrl = 'api/heroes'; // URL to web api private headers = new Headers({'Content-Type': 'application/json'}); constructor(private http: Http) {} getHeroes(): Promise<Hero[]> { return this.http.get(this.heroesUrl) .toPromise() .then(response => response.json().data as Hero[]) .catch(this.handleError); } private handleError(error: any): Promise<any> { console.error('An error occurred', error); // for demo purposes only return Promise.reject(error.message || error); } getHero(id: number): Promise<Hero> { const url = `${this.heroesUrl}/${id}`; return this.http.get(url) .toPromise() .then(response => response.json().data as Hero) .catch(this.handleError); } update(hero: Hero): Promise<Hero> { const url = `${this.heroesUrl}/${hero.id}`; return this.http .put(url, JSON.stringify(hero), {headers: this.headers}) .toPromise() .then(() => hero) .catch(this.handleError); } }
続いて、「hero-detail.component.html」に、<button>タグを追加。
<div *ngIf="hero"> <h2>{{hero.name}} details!</h2> <div> <label>id: </label>{{hero.id}}</div> <div> <label>name: </label> <input [(ngModel)]="hero.name" placeholder="name" /> </div> <button (click)="goBack()">Back</button> <button (click)="save()">Save</button> </div>
「hero-detail.component.ts」にsave()メソッドを追加します。
import 'rxjs/add/operator/switchMap'; import { Component, Input, OnInit } from '@angular/core'; import { ActivatedRoute, ParamMap } from '@angular/router'; import { Location } from '@angular/common'; import { Hero } from './hero'; import { HeroService } from './hero.service'; @Component({ selector: 'hero-detail', templateUrl: './hero-detail.component.html', styleUrls: ['./hero-detail.component.css'] }) export class HeroDetailComponent implements OnInit { @Input() hero: Hero; constructor( private heroService: HeroService, private route: ActivatedRoute, private location: Location ) {} ngOnInit(): void { this.route.paramMap .switchMap((params: ParamMap) => this.heroService.getHero(+params.get('id'))) .subscribe(hero => this.hero = hero); } goBack(): void { this.location.back(); } save(): void { this.heroService.update(this.hero) .then(() => this.goBack()); } }
ブラウザで確認。
試しに、変更して「Save」ボタンを押してみます。
変更が反映されています。
Add the ability to add heroes
「heroes.component.html 」に追加します。
import 'rxjs/add/operator/switchMap'; <h2>My Heroes</h2> <ul class="heroes"> <li *ngFor="let hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li> </ul> <div *ngIf="selectedHero"> <h2> {{selectedHero.name | uppercase}} is my hero </h2> <button (click)="gotoDetail()">View Details</button> </div> <div> <label>Hero name:</label> <input #heroName /> <button (click)="add(heroName.value); heroName.value=''">Add</button> </div>
「heroes.component.ts 」にadd()メソッドを追加します
import 'rxjs/add/operator/switchMap'; import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { Hero } from './hero'; import { HeroService } from './hero.service'; @Component({ selector: 'my-heroes', // templateUrl: './app.component.html', // styleUrls: ['./app.component.css'], templateUrl: './heroes.component.html', styleUrls: ['./heroes.component.css'] // providers: [HeroService] }) export class HeroesComponent implements OnInit { // title = 'Tour of Heroes'; heroes: Hero[]; selectedHero: Hero; constructor( private router: Router, private heroService: HeroService) {} getHeroes(): void { this.heroService.getHeroes().then(heroes => this.heroes = heroes); } ngOnInit(): void { this.getHeroes(); } onSelect(hero: Hero): void { this.selectedHero = hero; } gotoDetail(): void { this.router.navigate(['/detail', this.selectedHero.id]); } add(name: String): void { name = name.trim(); if(!name) { return; } this.heroService.create(name) .then(hero => { this.heroes.push(hero); this.selectedHero = null; }); } }
「hero.service.ts」にcreate()メソッドを追加
import { Injectable } from '@angular/core'; import { Headers, Http } from '@angular/http'; import 'rxjs/add/operator/toPromise'; import { Hero } from './hero'; @Injectable() export class HeroService { private heroesUrl = 'api/heroes'; // URL to web api private headers = new Headers({'Content-Type': 'application/json'}); constructor(private http: Http) {} getHeroes(): Promise<Hero[]> { return this.http.get(this.heroesUrl) .toPromise() .then(response => response.json().data as Hero[]) .catch(this.handleError); } private handleError(error: any): Promise{ console.error('An error occurred', error); // for demo purposes only return Promise.reject(error.message || error); } getHero(id: number): Promise { const url = `${this.heroesUrl}/${id}`; return this.http.get(url) .toPromise() .then(response => response.json().data as Hero) .catch(this.handleError); } update(hero: Hero): Promise { const url = `${this.heroesUrl}/${hero.id}`; return this.http .put(url, JSON.stringify(hero), {headers: this.headers}) .toPromise() .then(() => hero) .catch(this.handleError); } create(name: string): Promise { return this.http .post(this.heroesUrl, JSON.stringify({name: name}), {headers: this.headers}) .toPromise() .then(res => res.json().data as Hero) .catch(this.handleError); } }
ブラウザで確認。
「Add」を押してみる。
追加されました。
Add the ability to delete a hero
削除ボタンを追加します。「heroes.component.html」の
<h2>My Heroes</h2> <ul class="heroes"> <li *ngFor="let hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)"> <span class="badge">{{hero.id}}</span> <span>{{hero.name}}</span> <button class="delete" (click)="delete(hero); $event.stopPropagation()">×</button> </li> </ul> <div *ngIf="selectedHero"> <h2> {{selectedHero.name | uppercase}} is my hero </h2> <button (click)="gotoDetail()">View Details</button> </div> <div> <label>Hero name:</label> <input #heroName /> <button (click)="add(heroName.value); heroName.value=''">Add</button> </div>
「heroes.component.ts」にdelete()メソッドを追加します。
import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { Hero } from './hero'; import { HeroService } from './hero.service'; @Component({ selector: 'my-heroes', // templateUrl: './app.component.html', // styleUrls: ['./app.component.css'], templateUrl: './heroes.component.html', styleUrls: ['./heroes.component.css'] // providers: [HeroService] }) export class HeroesComponent implements OnInit { // title = 'Tour of Heroes'; heroes: Hero[]; selectedHero: Hero; constructor( private router: Router, private heroService: HeroService) {} getHeroes(): void { this.heroService.getHeroes().then(heroes => this.heroes = heroes); } ngOnInit(): void { this.getHeroes(); } onSelect(hero: Hero): void { this.selectedHero = hero; } gotoDetail(): void { this.router.navigate(['/detail', this.selectedHero.id]); } add(name: string): void { name = name.trim(); if (!name) { return; } this.heroService.create(name) .then(hero => { this.heroes.push(hero); this.selectedHero = null; }); } delete(hero: Hero): void { this.heroService .delete(hero.id) .then(() => { this.heroes = this.heroes.filter(h => h !== hero); if (this.selectedHero === hero) { this.selectedHero = null; } }); } }
「hero.service.ts」にdelete()メソッドを追加します。
import { Injectable } from '@angular/core'; import { Headers, Http } from '@angular/http'; import 'rxjs/add/operator/toPromise'; import { Hero } from './hero'; @Injectable() export class HeroService { private heroesUrl = 'api/heroes'; // URL to web api private headers = new Headers({'Content-Type': 'application/json'}); constructor(private http: Http) {} getHeroes(): Promise<Hero[]> { return this.http.get(this.heroesUrl) .toPromise() .then(response => response.json().data as Hero[]) .catch(this.handleError); } private handleError(error: any): Promise{ console.error('An error occurred', error); // for demo purposes only return Promise.reject(error.message || error); } getHero(id: number): Promise { const url = `${this.heroesUrl}/${id}`; return this.http.get(url) .toPromise() .then(response => response.json().data as Hero) .catch(this.handleError); } update(hero: Hero): Promise { const url = `${this.heroesUrl}/${hero.id}`; return this.http .put(url, JSON.stringify(hero), {headers: this.headers}) .toPromise() .then(() => hero) .catch(this.handleError); } create(name: string): Promise { return this.http .post(this.heroesUrl, JSON.stringify({name: name}), {headers: this.headers}) .toPromise() .then(res => res.json().data as Hero) .catch(this.handleError); } delete(id: number): Promise { const url = `${this.heroesUrl}/${id}`; return this.http.delete(url, {headers: this.headers}) .toPromise() .then(() => null) .catch(this.handleError); } }
button.delete { float:right; margin-top: 2px; margin-right: .8em; background-color: gray !important; color:white; }
ブラウザで確認。
削除ができます。
Add the ability to search by name
検索機能を追加します。「angular-tour-of-heroes」>「src」>「app」を選択した状態で右クリックし、「新規(W)」>「その他(O)...」
「TypeScript」>「TypeScript source File」を選択し、「次へ(N)>」をクリック。
「ファイル名(F):」を「hero-search.service.ts」とし「完了(F)」。
import { Injectable } from '@angular/core'; import { Http } from '@angular/http'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import { Hero } from './hero'; @Injectable() export class HeroSearchService { constructor(private http: Http) {} search(term: string): Observable<Hero[]> { return this.http .get(`api/heroes/?name=${term}`) .map(response => response.json().data as Hero[]); } }
続いて、「hero-search.component.html」を作成。「angular-tour-of-heroes」>「src」>「app」を選択した状態で右クリックし、「新規(W)」>「その他(O)...」
「Web」>「HTMLファイル」を選択。
「ファイル名(F):」を「hero-search.component.html」とし「次へ(N)>」。
「完了(F)」。
<div id="search-component"> <h4>Hero Search</h4> <input #searchBox id="search-box" (keyup)="search(searchBox.value)" /> <div> <div *ngFor="let hero of heroes | async" (click)="gotoDetail(hero)" class="search-result" > {{hero.name}} </div> </div> </div>
続いて、「hero-search.component.css」。
「hero-search.component.css」を作成。「angular-tour-of-heroes」>「src」>「app」を選択した状態で右クリックし、「新規(W)」>「その他(O)...」
「Web」>「CSSファイル」を選択。
「ファイル名(F):」を「hero-search.component.css」とし「次へ(N)>」。
「完了(F)」。
.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; }
「hero-search.component.ts」。
「hero-search.component.ts」を作成。「angular-tour-of-heroes」>「src」>「app」を選択した状態で右クリックし、「新規(W)」>「その他(O)...」
「TypeScript」>「TypeScript source File」を選択し、「次へ(N)>」をクリック。
「ファイル名(F):」を「hero-search.component.ts」とし「完了(F)」。
import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { Observable } from 'rxjs/Observable'; import { Subject } from 'rxjs/Subject'; // Observable class extensions import 'rxjs/add/observable/of'; // Observable operators import 'rxjs/add/operator/catch'; import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/distinctUntilChanged'; import { HeroSearchService } from './hero-search.service'; import { Hero } from './hero'; @Component({ selector: 'hero-search', templateUrl: './hero-search.component.html', styleUrls: [ './hero-search.component.css' ], providers: [HeroSearchService] }) export class HeroSearchComponent implements OnInit { heroes: Observable<Hero[]>; private searchTerms = new Subject<string>(); constructor( private heroSearchService: HeroSearchService, private router: Router) {} // Push a search term into the observable stream. search(term: string): void { this.searchTerms.next(term); } ngOnInit(): void { this.heroes = this.searchTerms .debounceTime(300) // wait 300ms after each keystroke before considering the term .distinctUntilChanged() // ignore if next search term is same as previous .switchMap(term => term // switch to new observable each time the term changes // return the http search observable ? this.heroSearchService.search(term) // or the observable of empty heroes if there was no search term : Observable.of<Hero[]>([])) .catch(error => { // TODO: add real error handling console.log(error); return Observable.of<Hero[]>([]); }); } gotoDetail(hero: Hero): void { let link = ['/detail', hero.id]; this.router.navigate(link); } }
エラー!
「Identifier 'link' is never reassinged; use 'const' instead of 'let'」と言ってます。
コードをよく見ると、
gotoDetail(hero: Hero): void { let link = ['/detail', hero.id]; this.router.navigate(link); }
「['/detail', hero.id]」が変数として認識されていませんね...致し方ないですが、「Jump to rule configuration」を選択して、「 "prefer-const": true, 」を消します。
{ "rulesDirectory": [ "node_modules/codelyzer" ], "rules": { "arrow-return-shorthand": true, "callable-types": true, "class-name": true, "comment-format": [ true, "check-space" ], "curly": true, "eofline": true, "forin": true, "import-blacklist": [ true, "rxjs" ], "import-spacing": false, "indent": [ true, "spaces" ], "interface-over-type-literal": true, "label-position": true, "max-line-length": [ true, 140 ], "member-access": false, "member-ordering": [ true, { "order": [ "static-field", "instance-field", "static-method", "instance-method" ] } ], "no-arg": true, "no-bitwise": true, "no-console": [ true, "debug", "info", "time", "timeEnd", "trace" ], "no-construct": true, "no-debugger": true, "no-duplicate-super": true, "no-empty": false, "no-empty-interface": true, "no-eval": true, "no-inferrable-types": [ true, "ignore-params" ], "no-misused-new": true, "no-non-null-assertion": true, "no-shadowed-variable": true, "no-string-literal": false, "no-string-throw": true, "no-switch-case-fall-through": true, "no-trailing-whitespace": true, "no-unnecessary-initializer": true, "no-unused-expression": true, "no-use-before-declare": true, "no-var-keyword": true, "object-literal-sort-keys": false, "one-line": [ true, "check-open-brace", "check-catch", "check-else", "check-whitespace" ], "quotemark": [ true, "single" ], "radix": true, "semicolon": [ true, "always" ], "triple-equals": [ true, "allow-null-check" ], "typedef-whitespace": [ true, { "call-signature": "nospace", "index-signature": "nospace", "parameter": "nospace", "property-declaration": "nospace", "variable-declaration": "nospace" } ], "typeof-compare": true, "unified-signatures": true, "variable-name": false, "whitespace": [ true, "check-branch", "check-decl", "check-operator", "check-separator", "check-type" ], "directive-selector": [ true, "attribute", ["app", "my*", "hero*"], "camelCase" ], "component-selector": [ true, "element", ["app", "my*", "hero*"], "kebab-case" ], "use-input-property-decorator": true, "use-output-property-decorator": true, "use-host-property-decorator": true, "no-input-rename": true, "no-output-rename": true, "use-life-cycle-interface": true, "use-pipe-transform-interface": true, "component-class-suffix": true, "directive-class-suffix": true, "no-access-missing-member": true, "templates-use-public": true, "invoke-injectable": true } }
保存。エラーは消えたけど...「Angular DOC」の見本のソースの「tslint.json」の設定でも「 "prefer-const": true, 」削除されてましたし、ドンマイ。
Add the search component to the dashboard
検索機能を表示できるように「dashboard.component.html」に追加。
<h3>Top Heroes</h3> <div class="grid grid-pad"> <div *ngFor="let hero of heroes" [routerLink]="['/detail', hero.id]" class="col-1-4"> <div class="module hero"> <h4>{{hero.name}}</h4> </div> </div> </div> <hero-search></hero-search>
「app.module.ts 」で「HeroSearchComponent」をインポートします。
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; // 追加 // Imports for loading & configuring the in-memory web api import { InMemoryWebApiModule } from 'angular-in-memory-web-api'; import { InMemoryDataService } from './in-memory-data.service'; import { AppComponent } from './app.component'; import { DashboardComponent } from './dashboard.component'; import { HeroDetailComponent } from './hero-detail.component'; import { HeroesComponent } from './heroes.component'; import { HeroService } from './hero.service'; import { AppRoutingModule } from './app-routing.module'; import { HeroSearchComponent } from './hero-search.component'; // 追加 @NgModule({ declarations: [ AppComponent, DashboardComponent, HeroDetailComponent, HeroesComponent, HeroSearchComponent // 追加 ], imports: [ BrowserModule, FormsModule, AppRoutingModule, HttpModule, // 追加 InMemoryWebApiModule.forRoot(InMemoryDataService), // 追加 AppRoutingModule ], providers: [ HeroService ], bootstrap: [ AppComponent ] }) export class AppModule { }
一応、コマンドプロンプト側にて「Ctrl + C」でAngularJSの開発用サーバーを一旦、停止し「npm start」で再起動しておきます。
ブラウザで確認。
検索も表示できました。
検索結果も大丈夫そうです。
ちなみに、html系のファイルに警告が出てしまっていますが、Eclipseになんかプラグインとか入れないとダメかもです。(「Angular IDE 2017 CI8」とかが面倒みてくれると思ったのですが)
エラーではないのですが、しばらくはこんな感じで警告が出てしまうことになりますかね。
むちゃくちゃながくなってしまいましたが、「tslint.json」とかの設定はAngular DOCの
設定まわりで止まるのって本当に調べるので時間が取られて疲れますね...。
⇩ そして、なにやらAngularJSの評判が芳しくないのが気になりますね...
・Angular 2/4が狭量で遅すぎる理由 | プロダクト・サービス | POSTD