本节中,我们来共同完成前台对接后台前的最后准备工作。
# 初始化
## C层
在C层中,我们添加一个`onSubmit`方法,用于V层点击`提交`按钮时触发。
TeacherAddComponent
```js
export class TeacherAddComponent implements OnInit {
name: string;
username: string;
email: string;
sex: boolean;
ngOnInit(): void {
}
/**
* 将要保存的教师信息提交给后台
* 当声明方法为public(此关键字可省略)时,相当于绑定到了V层,V层中可以进行调用或是绑定操作。
*/
public onSubmit(): void {
console.log('点击提交按钮'); ➊
}
}
```
* ➊该方法被成功触发时,向控制台打印测试内容。
## V层
在表单中,使用`ngSubmit`绑定表单单提交时触发的方法。
teacher-add.component.html
```html
<pre>{{name}} {{username}} {{email}} {{sex}}</pre>
<form id="teacherAddForm" (ngSubmit)="onSubmit()"> ➊
```
* ➊ 当表单提交时,触发C层的`onSubmit`方法
## 测试
![](https://img.kancloud.cn/64/99/64998d00d838fea64c721e544b477ad3_706x502.gif)
# 向后台发送请求
```js
import {HttpClient} from '@angular/common/http';
constructor(private httpClient: HttpClient) { ★
}
/**
* 将要保存的教师信息提交给后台
* 当声明方法为public(此关键字可省略)时,相当于绑定到了V层,V层中可以进行调用或是绑定操作。
*/
public onSubmit(): void {
const url = 'http://localhost:8080/Teacher';
const teacher = { ➊
name: this.name, ➋
username: this.username,
email: this.email,
sex: this.sex
};
console.log(teacher); ➌
this.httpClient.post(url, teacher) ➍
.subscribe(function () { ➎
console.log('添加成功');
}, (response) => { ➏
console.error('请求发生错误', response);
});
}
```
* ★ 不解释
* ➊定义要传入后台的数据对象,该对象起名为teacher,对象中有4个属性分别为name,username,email,sex。属性的值分别为当前V层表单中用户输入的值(数据双向绑定)。
* ➋用当前组件的name值(即V层用户输入的值)来给teacher对象的name属性赋值。
* ➌开发测试信息,为了在控制台中查看是否正确的为teacher赋值了。
* ➍使用httpClient对象,向`url`地址发起`post`请求,请求的内容为`teacher`。
* ➎匿名函数,当请求成功时调用此方法**由于前面我们讲过的原因,此方法将在后面弃用**。
* ➏匿名箭头函数,当请求失败时调用此方法。
# 测试
![](https://img.kancloud.cn/15/ab/15ab89dc8eefbaa6fdad3bae3a5e12de_706x502.gif)
请求成功的发出,由于后台无相关功能的原因,触发了我们定义的请求发生错误代码,且控制台打印的`teacher`信息正确,符合预期。
# 本节小测
## 请思考
我们前台提到过一个原则,即:规避在代码直接输入字符串。但`http://localhost:8080/Teacher`此字符串我们却分别在`AppComponent`及`TeacherAddComponet`中分别写了一次,这显然违背了上述原则。如果并不需要考虑编码,你有什么解决的思想吗?
> 程序员 = 拥有编程技能的工人;工程师 = 程序员 + 拥有编程思想的科技工作者。只有着重学习编程思想、反复练习编程技能,才能成为优秀的软件工程师。
## 上节答案1
我们已经学习过了`ngFor`、`ngIf`、`ngModel`,请尝试总结在功能及使用方法上的异同点。
| 指令 | 功能 | 使用方法 |
| --- | --- | --- |
| ngFor | 按实际情况,复制宿主dom代码变成0行、1行或多行HTML代码 | 以`*`打头,使用方法与一般的dom属性相同 |
| ngIf | 按实际情况,选择保留或移除宿dom | 以`*`打头,使用方法与一般的dom属性相同 |
| ngModel | 不改变宿主dom的结构,获取(并设置)宿主dom的值 | 使用`([])`进行包裹 |
> dom = Document Object Model 文档对象模块。在html,我们习惯性的称为html dom。可以简单的理解为某标签及包含的子标签(如有)。
*****
**总结:** 我们把改变dom结构的指令称为结构型指令,比如`ngFor`;把不改变dom结构的指令称为属性型指令,比如`ngModel`。
*****
## 上节答案2
测试的方法有很多种,在这里给出其中的一种:
V层
```
<form id="teacherAddForm" (ngSubmit)="onSubmit()">
<div>
<label for="name">姓名:</label>
<input type="text" id="name" name="name" [(ngModel)]="name"/>
</div>
<div>
<label for="name">测试姓名:</label>
<input type="text" id="name1" name="name1" [(ngModel)]="name1"/>
</div>
<div>
<button>提交</button>
</div>
</form>
```
C层
```
export class TestComponent {
name: string;
name1: string;
public onSubmit(): void {
console.log(this.name); ➊
this.name1 = this.name; ➋
}
}
```
* ➊ V层中的姓名变化后,点击提交按钮打印C层中name的值,打印的值同V层中的值相同,说明V层的表单变化时时影响了C层变量的值。
* ➋ 在C层中对变量name1赋新值,此时V层中对应的测试姓名表单中的内容时时发生了变化,说明C层中的变量值发生变化时,实时的传递给了V层。
# 参考文档
| 名称 | 链接 | 预计学习时长(分) |
| --- | --- | --- |
| 使用ngSubmit提交表单 | [https://www.angular.cn/guide/forms#submit-the-form-with-ngsubmit](https://www.angular.cn/guide/forms#submit-the-form-with-ngsubmit) | 2 |
| 发起一个POST请求 | [https://angular.cn/guide/http#making-a-post-request](https://angular.cn/guide/http#making-a-post-request) | 5 |
| HTTP 方法:GET 对比 POST(文章下面的笔记更精彩) | [https://www.runoob.com/tags/html-httpmethods.html](https://www.runoob.com/tags/html-httpmethods.html) | 10 |
| 源码地址 | [https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step2.3.3](https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step2.3.3) | - |
- 序言
- 第一章:Hello World
- 第一节:Angular准备工作
- 1 Node.js
- 2 npm
- 3 WebStorm
- 第二节:Hello Angular
- 第三节:Spring Boot准备工作
- 1 JDK
- 2 MAVEN
- 3 IDEA
- 第四节:Hello Spring Boot
- 1 Spring Initializr
- 2 Hello Spring Boot!
- 3 maven国内源配置
- 4 package与import
- 第五节:Hello Spring Boot + Angular
- 1 依赖注入【前】
- 2 HttpClient获取数据【前】
- 3 数据绑定【前】
- 4 回调函数【选学】
- 第二章 教师管理
- 第一节 数据库初始化
- 第二节 CRUD之R查数据
- 1 原型初始化【前】
- 2 连接数据库【后】
- 3 使用JDBC读取数据【后】
- 4 前后台对接
- 5 ng-if【前】
- 6 日期管道【前】
- 第三节 CRUD之C增数据
- 1 新建组件并映射路由【前】
- 2 模板驱动表单【前】
- 3 httpClient post请求【前】
- 4 保存数据【后】
- 5 组件间调用【前】
- 第四节 CRUD之U改数据
- 1 路由参数【前】
- 2 请求映射【后】
- 3 前后台对接【前】
- 4 更新数据【前】
- 5 更新某个教师【后】
- 6 路由器链接【前】
- 7 观察者模式【前】
- 第五节 CRUD之D删数据
- 1 绑定到用户输入事件【前】
- 2 删除某个教师【后】
- 第六节 代码重构
- 1 文件夹化【前】
- 2 优化交互体验【前】
- 3 相对与绝对地址【前】
- 第三章 班级管理
- 第一节 JPA初始化数据表
- 第二节 班级列表
- 1 新建模块【前】
- 2 初识单元测试【前】
- 3 初始化原型【前】
- 4 面向对象【前】
- 5 测试HTTP请求【前】
- 6 测试INPUT【前】
- 7 测试BUTTON【前】
- 8 @RequestParam【后】
- 9 Repository【后】
- 10 前后台对接【前】
- 第三节 新增班级
- 1 初始化【前】
- 2 响应式表单【前】
- 3 测试POST请求【前】
- 4 JPA插入数据【后】
- 5 单元测试【后】
- 6 惰性加载【前】
- 7 对接【前】
- 第四节 编辑班级
- 1 FormGroup【前】
- 2 x、[x]、{{x}}与(x)【前】
- 3 模拟路由服务【前】
- 4 测试间谍spy【前】
- 5 使用JPA更新数据【后】
- 6 分层开发【后】
- 7 前后台对接
- 8 深入imports【前】
- 9 深入exports【前】
- 第五节 选择教师组件
- 1 初始化【前】
- 2 动态数据绑定【前】
- 3 初识泛型
- 4 @Output()【前】
- 5 @Input()【前】
- 6 再识单元测试【前】
- 7 其它问题
- 第六节 删除班级
- 1 TDD【前】
- 2 TDD【后】
- 3 前后台对接
- 第四章 学生管理
- 第一节 引入Bootstrap【前】
- 第二节 NAV导航组件【前】
- 1 初始化
- 2 Bootstrap格式化
- 3 RouterLinkActive
- 第三节 footer组件【前】
- 第四节 欢迎界面【前】
- 第五节 新增学生
- 1 初始化【前】
- 2 选择班级组件【前】
- 3 复用选择组件【前】
- 4 完善功能【前】
- 5 MVC【前】
- 6 非NULL校验【后】
- 7 唯一性校验【后】
- 8 @PrePersist【后】
- 9 CM层开发【后】
- 10 集成测试
- 第六节 学生列表
- 1 分页【后】
- 2 HashMap与LinkedHashMap
- 3 初识综合查询【后】
- 4 综合查询进阶【后】
- 5 小试综合查询【后】
- 6 初始化【前】
- 7 M层【前】
- 8 单元测试与分页【前】
- 9 单选与多选【前】
- 10 集成测试
- 第七节 编辑学生
- 1 初始化【前】
- 2 嵌套组件测试【前】
- 3 功能开发【前】
- 4 JsonPath【后】
- 5 spyOn【后】
- 6 集成测试
- 7 @Input 异步传值【前】
- 8 值传递与引入传递
- 9 @PreUpdate【后】
- 10 表单验证【前】
- 第八节 删除学生
- 1 CSS选择器【前】
- 2 confirm【前】
- 3 功能开发与测试【后】
- 4 集成测试
- 5 定制提示框【前】
- 6 引入图标库【前】
- 第九节 集成测试
- 第五章 登录与注销
- 第一节:普通登录
- 1 原型【前】
- 2 功能设计【前】
- 3 功能设计【后】
- 4 应用登录组件【前】
- 5 注销【前】
- 6 保留登录状态【前】
- 第二节:你是谁
- 1 过滤器【后】
- 2 令牌机制【后】
- 3 装饰器模式【后】
- 4 拦截器【前】
- 5 RxJS操作符【前】
- 6 用户登录与注销【后】
- 7 个人中心【前】
- 8 拦截器【后】
- 9 集成测试
- 10 单例模式
- 第六章 课程管理
- 第一节 新增课程
- 1 初始化【前】
- 2 嵌套组件测试【前】
- 3 async管道【前】
- 4 优雅的测试【前】
- 5 功能开发【前】
- 6 实体监听器【后】
- 7 @ManyToMany【后】
- 8 集成测试【前】
- 9 异步验证器【前】
- 10 详解CORS【前】
- 第二节 课程列表
- 第三节 果断
- 1 初始化【前】
- 2 分页组件【前】
- 2 分页组件【前】
- 3 综合查询【前】
- 4 综合查询【后】
- 4 综合查询【后】
- 第节 班级列表
- 第节 教师列表
- 第节 编辑课程
- TODO返回机制【前】
- 4 弹出框组件【前】
- 5 多路由出口【前】
- 第节 删除课程
- 第七章 权限管理
- 第一节 AOP
- 总结
- 开发规范
- 备用