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