# 更新教师 本节我们开始定制保存按钮触发的`onSubmit()`方法来完成与后台的对接,完成教师的更新功能。 我们为大家提供的后台接口信息如下: ```bash PUT /teacher/{id} ``` | **类型Type** | **名称Name** | **描述Description** | **类型Schema** | | ------------ | ------------ | ------------------- | ------------------------------------------------------------ | | Body | teacher | 教师 | `{username: string, name: string, email: string, sex: boolean}` | | Response | 成功 | Status Code: 204 | `{id: number, username: string, name: string, email: string, sex: boolean}` | ## 双向数据绑定 Angular模板驱动表单的`[(ngModel)]`提供了一种机制:当用户变更表单中的内容时,内容会实时的更新到C层的变量上;C层变量发生变更时,内容也会实时的更新到表单中。我们把这种机制称为:双向数据绑定。 我们简单改写下`onSubmit()`方法,使其打印当前的`teacher`属性至控制台: ```typescript +++ b/first-app/src/app/edit/edit.component.ts @@ -33,6 +33,6 @@ export class EditComponent implements OnInit { } onSubmit(): void { - console.log('点击提交按钮'); + console.log(this.teacher); } } ``` ![image-20210227132204848](https://img.kancloud.cn/45/2f/452fe18856278f4550ee8de46a5c443f_2306x620.png) 此时当我们变更姓名时,能够在V层的中能过`{{teacher | json}}`实时地查看到C层`teacher`的变化情况,点击保存按钮时可以看到`name`的值也进行了同步变更。 这便是**双向数据绑定**的魅力 ---- 当一方数据变化时,另一方的数据也同步发生变化。 ## 数据更新 接下来开始完成数据更新功能,首先:写注释! ```typescript +++ b/first-app/src/app/edit/edit.component.ts @@ -33,6 +33,8 @@ export class EditComponent implements OnInit { } onSubmit(): void { - console.log('点击提交按钮'); + console.log(this.teacher); + // 获取ID,拼接URL + // 发起请求,更新教师,成功时打印请求结果并刷新教师列表查看效果,失败时打印失败结果 } } ``` 然后才是功能开发: ```typescript +++ b/first-app/src/app/edit/edit.component.ts @@ -35,6 +35,11 @@ export class EditComponent implements OnInit { onSubmit(): void { console.log(this.teacher); // 获取ID,拼接URL + const url = 'http://angular.api.codedemo.club:81/teacher/' + + this.activeRoute.snapshot.params.id; // 发起请求,更新教师,成功时打印请求结果并刷新教师列表查看效果,失败时打印失败结果 + this.httpClient.put(url, this.teacher) + .subscribe(data => console.log('更新成功', data), + error => console.log('更新错误', error)); } } ``` ![image-20210227133131898](https://img.kancloud.cn/a7/58/a758905523181acb729c714ebde4de34_2448x678.png) 再次刷新当前页面,教师列表中的数据也同步的更新了。 ![image-20210227133308832](https://img.kancloud.cn/20/27/202768b83d79266a520b1b3311508612_3566x244.png) 嗯,甚好。 ## 父子组件 如果编辑组件更新某个教师后,教师列表能够同步的刷新。那当然也是极好的。为此,我们需要深入对当前的教师列表、教师编辑组件进行学习。 若要教师列表组件的数据被更新,首先我们要找到其组件中数据更新对应的代码,打开组件C层文件后发现其`ngOnInit`方法中完成了获取后台教师列表的功能: ```typescript /** * 组件初始化完成后将被自动执行一次 */ ngOnInit(): void { this.httpClient.get<[]>('http://angular.api.codedemo.club:81/teacher') .subscribe(teachers => this.teachers = teachers); } } ``` 如若实现更新后刷新教师列表,则想办法调用该`ngOnInit`方法即可: ```typescript +++ b/first-app/src/app/edit/edit.component.ts @@ -39,7 +39,10 @@ export class EditComponent implements OnInit { this.activeRoute.snapshot.params.id; // 发起请求,更新教师,成功时打印请求结果并刷新教师列表查看效果,失败时打印失败结果 this.httpClient.put(url, this.teacher) - .subscribe(data => console.log('更新成功', data), + .subscribe(data => { + console.log('更新成功', data); + // 在此调用教师列表App组个的ngOnInit方法,即可实现更新后重新刷新教师列表的功能 + }, error => console.log('更新错误', error)); } } ``` 非常幸运的是可能由于Angular早到想到了这层需求(实际上没有,因为Anguar并不推荐我们这么样),我们可以在子组件Edit中以依赖注入的方式来获取到其父App组件: ```typescript +++ b/first-app/src/app/edit/edit.component.ts @@ -1,6 +1,7 @@ import {Component, OnInit} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {HttpClient} from '@angular/common/http'; +import {AppComponent} from '../app.component'; @Component({ selector: 'app-edit', @@ -17,7 +18,8 @@ export class EditComponent implements OnInit { }; constructor(private activeRoute: ActivatedRoute, - private httpClient: HttpClient) { + private httpClient: HttpClient, + private appComponent: AppComponent) { } ngOnInit(): void { ``` 接着调用该父组件对应的`ngOnInit`方法,便可实现更新后自动刷新教师列表的功能: ```typescript --- a/first-app/src/app/edit/edit.component.ts +++ b/first-app/src/app/edit/edit.component.ts @@ -44,6 +44,7 @@ export class EditComponent implements OnInit { .subscribe(data => { console.log('更新成功', data); // 在此调用教师列表App组个的ngOnInit方法,即可实现更新后重新刷新教师列表的功能 + this.appComponent.ngOnInit(); }, error => console.log('更新错误', error)); } ``` ![image-20210227134817766](https://img.kancloud.cn/bf/b0/bfb082682b420f4c0e1840246b80e702_2166x658.png) 总结:Angular的依赖注入不仅仅能注入服务,还可以注入父组件。依赖注入只所以会成功,是因为 Angular有注入该类型实例的能力;而依赖注入只所以会失败,则是因为Anuglar没有注入该类型实例的能力。 ## 本节作业 参考教师添加组件,为教师编辑组件添加样式,美化该教师编辑组件界面(如果在第一小节中已完成,请忽略)。同时去除在V层的测试痕迹`{{teacher | json}}`。 > 纸上得来终觉浅,绝知此事要躬行。看似简单的bootstrap界面美化,你成功了吗? 本节作业无参考答案,请完成本节作业后继续学习下一节。 | 名称 | 地址 | | | -------- | ------------------------------------------------------------ | ---- | | 双向绑定 | [https://angular.cn/guide/two-way-binding#two-way-binding](https://angular.cn/guide/two-way-binding#two-way-binding) | | | 本节源码 | [https://github.com/mengyunzhi/angular11-guild/archive/step2.4.5.zip](https://github.com/mengyunzhi/angular11-guild/archive/step2.4.5.zip) | |