1. 程式人生 > 實用技巧 >Angular(16) - 從服務端獲取資料 - 官方教程英雄指南之英雄的CRUD (詳細解說)

Angular(16) - 從服務端獲取資料 - 官方教程英雄指南之英雄的CRUD (詳細解說)

1 通過 id 獲取英雄, 暴露 getHero(id: number): Observable<Hero> 返回可觀察物件 Hero, 可以看到,不同的地方在於獲取的地址變成了 ${this.heroesUrl}/${id}

src/app/hero.service.ts
/** GET hero by id. Will 404 if id not found */
getHero(id: number): Observable<Hero> {
  const url = `${this.heroesUrl}/${id}`;
  return this.http.get<Hero>(url).pipe(
    tap(_ => this.log(`fetched hero id=${id}`)),
    catchError(this.handleError<Hero>(`getHero id=${id}`))
  );
}

2 修改英雄

  • 2.1 在 hero-detail.component.html 模板底部增加儲存按鈕
src/app/hero-detail/hero-detail.component.html
<button (click)="save()">save</button>
  • 2.2 增加相應的儲存事件
src/app/hero-detail/hero-detail.component.ts
save(): void {
  this.heroService.updateHero(this.hero)
    .subscribe(() => this.goBack());
}
  • 2.3 增加儲存的服務方法
src/app/hero.service.ts
/** PUT: update the hero on the server */
updateHero(hero: Hero): Observable<any> {
  return this.http.put(this.heroesUrl, hero, this.httpOptions).pipe(
    tap(_ => this.log(`updated hero id=${hero.id}`)),
    catchError(this.handleError<any>('updateHero'))
  );
}

HttpClient.put() 方法接受三個引數:

URL 地址
要修改的資料(這裡就是修改後的英雄)
選項
  • 2.4 增加Options, 其實就是定義格式為json
httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};

3 新增新英雄

  • 3.1 修改模板程式碼,增加 add 按鈕
src/app/heroes/heroes.component.html 
<div>
  <label>Hero name:
    <input #heroName />
  </label>
  <!-- (click) passes input value to add() and then clears the input -->
  <button (click)="add(heroName.value); heroName.value=''">
    add
  </button>
</div>
  • 3.2 增加模板後臺事件
src/app/heroes/heroes.component.ts
add(name: string): void {
  name = name.trim();
  if (!name) { return; }
  this.heroService.addHero({ name } as Hero)
    .subscribe(hero => {
      this.heroes.push(hero);
    });
}
  • 3.3 增加相應的服務
src/app/heroes/heroes.component.ts
/** POST: add a new hero to the server */
addHero(hero: Hero): Observable<Hero> {
  return this.http.post<Hero>(this.heroesUrl, hero, this.httpOptions).pipe(
    tap((newHero: Hero) => this.log(`added hero w/ id=${newHero.id}`)),
    catchError(this.handleError<Hero>('addHero'))
  );
}

4 刪除英雄

  • 4.1 修改模板, 在每個迴圈的li後面增加一個刪除按鈕
src/app/heroes/heroes.component.html
<ul class="heroes">
  <li *ngFor="let hero of heroes">
    <a routerLink="/detail/{{hero.id}}">
      <span class="badge">{{hero.id}}</span> {{hero.name}}
    </a>
    <button class="delete" title="delete hero"
      (click)="delete(hero)">x</button>
  </li>
</ul>
  • 4.2 增加模板的刪除事件, 這裡有兩個事情, 1是將英雄篩選,不包含當前刪除的英雄, 二是從服務中刪除掉這個英雄. 可以看出,這裡是先處理前端再處理後端的,原因是後端可能要時間,也有可能返回失敗
src/app/heroes/heroes.component.ts
delete(hero: Hero): void {
  this.heroes = this.heroes.filter(h => h !== hero);
  this.heroService.deleteHero(hero).subscribe();
}
  • 4.3 修改對應的HeroService方法, 這裡也是提交到對應的 ${this.heroesUrl}/${id}
src/app/hero.service.ts 
/** DELETE: delete the hero from the server */
deleteHero(hero: Hero | number): Observable<Hero> {
  const id = typeof hero === 'number' ? hero : hero.id;
  const url = `${this.heroesUrl}/${id}`;

  return this.http.delete<Hero>(url, this.httpOptions).pipe(
    tap(_ => this.log(`deleted hero id=${id}`)),
    catchError(this.handleError<Hero>('deleteHero'))
  );
}