From 42004e7dd84f0d7352b29204e37210e8fc6f960b Mon Sep 17 00:00:00 2001 From: Nils Dittberner Date: Thu, 17 Oct 2019 11:55:09 +0200 Subject: [PATCH] toh-pt6 --- package-lock.json | 5 ++ package.json | 1 + src/app/app.module.ts | 28 ++++++---- src/app/hero-detail/hero-detail.component.html | 1 + src/app/hero-detail/hero-detail.component.ts | 5 ++ src/app/hero.service.ts | 73 ++++++++++++++++++++++---- src/app/heroes/heroes.component.css | 22 ++++++++ src/app/heroes/heroes.component.html | 11 ++++ src/app/heroes/heroes.component.ts | 14 +++++ src/app/in-memory-data.service.ts | 32 +++++++++++ 10 files changed, 173 insertions(+), 19 deletions(-) create mode 100644 src/app/in-memory-data.service.ts diff --git a/package-lock.json b/package-lock.json index cafa8b8..5b2e8b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2226,6 +2226,11 @@ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, + "angular-in-memory-web-api": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/angular-in-memory-web-api/-/angular-in-memory-web-api-0.9.0.tgz", + "integrity": "sha512-//PiJ5qb1+Yf/N7270ioQqR2laf4/Irjavg+M+WEn8y4At9LUoYgbQ5HVwvM5xUTlVlL0XkbJRLxREcGGNdIEw==" + }, "ansi-colors": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", diff --git a/package.json b/package.json index 1b146d2..d436de1 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@angular/platform-browser": "~8.2.9", "@angular/platform-browser-dynamic": "~8.2.9", "@angular/router": "~8.2.9", + "angular-in-memory-web-api": "^0.9.0", "rxjs": "~6.4.0", "tslib": "^1.10.0", "zone.js": "~0.9.1" diff --git a/src/app/app.module.ts b/src/app/app.module.ts index c12842a..a9e24d8 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,13 +1,16 @@ -import { BrowserModule } from '@angular/platform-browser'; -import { NgModule } from '@angular/core'; +import {BrowserModule} from '@angular/platform-browser'; +import {NgModule} from '@angular/core'; -import { AppComponent } from './app.component'; -import { HeroesComponent } from './heroes/heroes.component'; +import {AppComponent} from './app.component'; +import {HeroesComponent} from './heroes/heroes.component'; import {FormsModule} from '@angular/forms'; -import { HeroDetailComponent } from './hero-detail/hero-detail.component'; -import { MessagesComponent } from './messages/messages.component'; -import { AppRoutingModule } from './app-routing.module'; -import { DashboardComponent } from './dashboard/dashboard.component'; +import {HeroDetailComponent} from './hero-detail/hero-detail.component'; +import {MessagesComponent} from './messages/messages.component'; +import {AppRoutingModule} from './app-routing.module'; +import {DashboardComponent} from './dashboard/dashboard.component'; +import {HttpClientModule} from "@angular/common/http"; +import {HttpClientInMemoryWebApiModule} from "angular-in-memory-web-api"; +import {InMemoryDataService} from "./in-memory-data.service"; @NgModule({ declarations: [ @@ -20,9 +23,14 @@ import { DashboardComponent } from './dashboard/dashboard.component'; imports: [ BrowserModule, FormsModule, - AppRoutingModule + AppRoutingModule, + HttpClientModule, + HttpClientInMemoryWebApiModule.forRoot( + InMemoryDataService, {dataEncapsulation: false} + ) ], providers: [], bootstrap: [AppComponent] }) -export class AppModule { } +export class AppModule { +} diff --git a/src/app/hero-detail/hero-detail.component.html b/src/app/hero-detail/hero-detail.component.html index 934ea7d..8ca8ea5 100644 --- a/src/app/hero-detail/hero-detail.component.html +++ b/src/app/hero-detail/hero-detail.component.html @@ -8,3 +8,4 @@ + diff --git a/src/app/hero-detail/hero-detail.component.ts b/src/app/hero-detail/hero-detail.component.ts index bcfe776..1fecca3 100644 --- a/src/app/hero-detail/hero-detail.component.ts +++ b/src/app/hero-detail/hero-detail.component.ts @@ -36,4 +36,9 @@ export class HeroDetailComponent implements OnInit { goBack() { this.location.back(); } + + save() { + this.heroService.udpateHero(this.hero) + .subscribe(() => this.goBack()); + } } diff --git a/src/app/hero.service.ts b/src/app/hero.service.ts index 6ac7347..8cca7de 100644 --- a/src/app/hero.service.ts +++ b/src/app/hero.service.ts @@ -1,24 +1,79 @@ -import { Injectable } from '@angular/core'; +import {Injectable} from '@angular/core'; -import { Hero } from './hero'; -import { HEROES } from './mock-heroes'; -import { Observable, of } from 'rxjs'; -import { MessageService } from './message.service'; +import {Hero} from './hero'; +import {Observable, of} from 'rxjs'; +import {MessageService} from './message.service'; +import {HttpClient, HttpHeaders} from "@angular/common/http"; +import {catchError, tap} from "rxjs/operators"; @Injectable({ providedIn: 'root' }) export class HeroService { - constructor(private messageService: MessageService) { } + private heroesUrl = 'api/heroes'; + + httpOptions = { + headers: new HttpHeaders({ 'Content-Type': 'application/json' }) + }; + + constructor( + private http: HttpClient, + private messageService: MessageService) { + } getHeroes(): Observable { this.messageService.add('HeroService: fetched heroes') - return of(HEROES); + return this.http.get(this.heroesUrl) + .pipe( + tap(_ => this.log('feteched heroes')), + catchError(this.handleError('getHeroes', [])) + ); } getHero(id: number): Observable { - this.messageService.add(`HeroService: fetched hero id=${id}`); - return of(HEROES.find(hero => hero.id === id)); + const url = `${this.heroesUrl}/${id}`; + return this.http.get(url).pipe( + tap(_ => this.log(`fetched hero id=${id}`)), + catchError(this.handleError(`getHero id=${id}`)) + ); + } + + addHero (hero: Hero): Observable { + return this.http.post(this.heroesUrl, hero, this.httpOptions).pipe( + tap((newHero: Hero) => this.log(`added hero w/ id=${newHero.id}`)), + catchError(this.handleError('addHero')) + ); + } + + deleteHero (hero: Hero | number): Observable { + const id = typeof hero === 'number' ? hero : hero.id; + const url = `${this.heroesUrl}/${id}`; + + return this.http.delete(url, this.httpOptions).pipe( + tap(_ => this.log(`deleted hero id=${id}`)), + catchError(this.handleError('deleteHero')) + ); + } + + private log(message: string) { + this.messageService.add(`HeroService: ${message}`); + } + + handleError(operation: string = 'operation', result?: T) { + return (error: any): Observable => { + console.error(error); + + this.log(`${operation} failed: ${error.message}`); + + return of(result as T); + } + } + + udpateHero(hero: Hero): Observable { + return this.http.put(this.heroesUrl, hero, this.httpOptions).pipe( + tap(_ => this.log(`updated hero id=${hero.id}`)), + catchError(this.handleError('updateHero')) + ); } } diff --git a/src/app/heroes/heroes.component.css b/src/app/heroes/heroes.component.css index 2ad3fef..6d1344b 100644 --- a/src/app/heroes/heroes.component.css +++ b/src/app/heroes/heroes.component.css @@ -49,3 +49,25 @@ margin-right: .8em; border-radius: 4px 0 0 4px; } + +button { + background-color: #eee; + border: none; + padding: 5px 10px; + border-radius: 4px; + cursor: pointer; + cursor: hand; + font-family: Arial; +} + +button:hover { + background-color: #cfd8dc; +} + +button.delete { + position: relative; + left: 194px; + top: -32px; + background-color: gray !important; + color: white; +} diff --git a/src/app/heroes/heroes.component.html b/src/app/heroes/heroes.component.html index 2eb180e..efbaa1e 100644 --- a/src/app/heroes/heroes.component.html +++ b/src/app/heroes/heroes.component.html @@ -1,8 +1,19 @@

My Heroes

+
+ + + +
diff --git a/src/app/heroes/heroes.component.ts b/src/app/heroes/heroes.component.ts index c33d11d..8994ada 100644 --- a/src/app/heroes/heroes.component.ts +++ b/src/app/heroes/heroes.component.ts @@ -22,4 +22,18 @@ export class HeroesComponent implements OnInit { this.heroService.getHeroes() .subscribe(heroes => this.heroes = heroes); } + + add(name: string): void { + name = name.trim(); + if (!name) { return; } + this.heroService.addHero({ name } as Hero) + .subscribe(hero => { + this.heroes.push(hero); + }); + } + + delete(hero: Hero): void { + this.heroes = this.heroes.filter(h => h !== hero); + this.heroService.deleteHero(hero).subscribe(); + } } diff --git a/src/app/in-memory-data.service.ts b/src/app/in-memory-data.service.ts new file mode 100644 index 0000000..455ce42 --- /dev/null +++ b/src/app/in-memory-data.service.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import {InMemoryDbService} from "angular-in-memory-web-api"; +import {Observable} from "rxjs"; +import {Hero} from "./hero"; + +@Injectable({ + providedIn: 'root' +}) +export class InMemoryDataService implements InMemoryDbService { + + constructor() { } + + createDb() { + const heroes = [ + { id: 11, name: 'Dr 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}; + } + + genId(heroes: Hero[]): number { + return heroes.length > 0 ? Math.max(...heroes.map(hero => hero.id)) + 1 : 11; + } +}