1. 程式人生 > >Angular6學習筆記12:HTTP(2)

Angular6學習筆記12:HTTP(2)

HTTP

繼學習筆記11以後,可以模擬的呼叫get方法,並且可以利用某一個ID去查詢某一個Hero的詳細資訊。

1.修改Hero的資訊

當需要修改某一個hero的名字的時候,當點選後退的時候,之前的所做的改變的資訊都會小時不在,在實際應用中,這些修改都應該是被儲存的,需要將修改後的資訊,傳輸給遠端的伺服器,進而的正真的修改這條資料。

在hero-detail的模版檔案中,增加一個save按鈕,並繫結一個點選事件save()。

<button (click)="save()">save</button>

實現save()方法:使用heroService中的updateHero()(稍後新增)

方法來儲存對某一個hero資訊修改,然後導航返回之前的一個檢視。

save(): void {
   this.heroService.updateHero(this.hero)
     .subscribe(() => this.goBack());
 }

新增updateHero() 方法,在專案中,在進行更新操作的時候,一般情況下發送的是put請求,所以,在這裡要呼叫http.put()方法,注:這裡的http是HttpClient的例項化的一個物件,將進行的更改儲存在遠端的伺服器上。

updateHero (hero: Hero): Observable<any> {
  return this.http.put(this.heroesUrl, hero, httpOptions).pipe(
    tap(_ => this.log(`updated hero id=${hero.id}`)),
    catchError(this.handleError<any>('updateHero'))
  );
}

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

  • URL 地址

  • 要修改的資料(這裡就是修改後的英雄)

  • 選項

一般情況,對於一系列中的其中一個事物進行修改,這個時候,可能就需要一個能唯一標示出這個事物的一個引數,常常用的是這個事物的ID,在當前的這個demo中,就可以使用每個hero的id對每個hero進行區別,從而知道具體更新的是哪一個hero。但有時候,(少數情況下)有時會會利用put方法進行新建操作(偶爾使用,不推薦)。

關於引數中的選項:option

有時在傳輸過程中,需要一個增加一些有特殊意思的請求頭,這個時候,就可以在option中使用,就是updateHero方法中的httpOptions

在這裡httpOptions:(由於這個httpOptions基本不會再進行改動,所以,用常量const 定義)

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};

此時,儲存重新整理瀏覽器,修改一個hero的name,然後點選save按鈕,然後在返回的導航中,就可以看到hero修改後的新name。

2.新建一個hero

每一個應用的資料不可能僅僅只能修改,當有一個新的hero來到時,這個時候,就需要將新的hero資訊增加到當前的hero列表中,我們需要一個輸入框,讓使用者通過這個輸入框輸入新的hero的name,並在這個輸入框的前面提示“Hero Name” ,使使用者意識到這個輸入的框的意思是輸入hero的Name,增加完輸入框以後,還需要增加一個按鈕,在這個按鈕上新增一個點選事件,當用戶點選這個按鈕的時候,開始獲取使用者在這個輸入框輸入的值,並將獲取的值傳送給遠端的伺服器,是遠端的伺服器的到這個新增的值,並新增至相應的資料庫中。

a.新增input,button等控制元件。

<div>
  <label>Hero name:
    <input #heroName />
  </label>
  <button (click)="add(heroName.value); heroName.value=''">
    add
  </button>
</div>

b.給button上新增點選事件add(heroName.value),當點選這個button的時候,會觸發清空之前填寫的資料,當用戶輸入了資料以後,會將這個資料轉換成Hero類似的物件(缺少hero的id屬性)。當儲存成功以後,會將這個hero的name放入(Array.push()方法)heroes的陣列中進行展示。

add(name: string): void {
    name = name.trim();
    if (!name) {
      return;
    }
    this.heroService.addHero({name} as Hero)
      .subscribe(hero => {
        this.heroes.push(hero);
      });
  }

c.在httpservice中增加一個addHero()方法,利用http.post()方法向遠端伺服器進行傳輸資料(http是HttpClient建立的一個例項)。

addHero(hero: Hero): Observable<Hero> {
    return this.http.post<Hero>(this.heroesUrl, hero, httpOptions).pipe(
      tap((hero: Hero) => this.log(`added hero w/ id=${hero.id}`)),
      catchError(this.handleError<Hero>('addHero'))
    );
  }

問題:為何此時沒有id屬性?

在某個一系列的事物中,這種進行事物唯一標示的操作,是來自於遠端的伺服器後端的分配的,新建的時候,就需要新建的資訊傳送給後端就可以了,然後遠端伺服器那邊會自動給當前的資料分配一個獨一無二的標示(ID)

3.刪除某一個Hero

當不要這個hero的時候,就需要將這個hero進行刪除,將需要刪除的hero傳給遠端的伺服器。

在每一個hero<li>標籤裡增加一個刪除的按鈕

<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>

使用一些CSS使這個刪除按鈕浮動在這個<li>的右邊。

.delete {
  position: relative;
  left: 194px;
  top: -32px;
  background-color: gray !important;
  color: white;
}

在類檔案中實現刪除button中的點選事件delete(hero)方法

delete(hero: Hero): void {
  this.heroes = this.heroes.filter(h => h !== hero);
  this.heroService.deleteHero(hero).subscribe();
}

雖然這個元件把刪除hero的邏輯委託給了 HeroService,但扔保留了更新它自己的hero列表的職責。 元件的 delete() 方法會在 HeroService 對伺服器的操作成功之前,先從列表中移除要刪除的hero

元件與 heroService.delete() 返回的 Observable 還完全沒有關聯。必須訂閱它

在heroService中新增delete()方法

 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, httpOptions).pipe(
      tap(_ => this.log(`deleted hero id=${id}`)),
      catchError(this.handleError<Hero>('deleteHero'))
    );
  }

注意

  • 它呼叫了 HttpClient.delete

  • URL 就是英雄的資源 URL 加上要刪除的英雄的 id

  • 你不用像 put 和 post 中那樣傳送任何資料。

  • 你仍要傳送 httpOptions

儲存,重新整理瀏覽器,就可以點選刪除按鈕,刪除需要刪除的hero