Angular6學習筆記12:HTTP(2)
HTTP
繼學習筆記11以後,可以模擬的呼叫get方法,並且可以利用某一個ID去查詢某一個Hero的詳細資訊。
1.修改Hero的資訊
當需要修改某一個hero的名字的時候,當點選後退的時候,之前的所做的改變的資訊都會小時不在,在實際應用中,這些修改都應該是被儲存的,需要將修改後的資訊,傳輸給遠端的伺服器,進而的正真的修改這條資料。
在hero-detail的模版檔案中,增加一個save按鈕,並繫結一個點選事件save()。
<button (click)="save()">save</button>
實現save()方法:使用heroService中的updateHero()(稍後新增)
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