参考前面章节实现班级列表组件及班级新增组件的方法,先使用终端进行app/klass路径,然后执行`ng g c edit`命令来创建班级编辑组件。 ``` panjiedeMac-Pro:klass panjie$ ng g c edit CREATE src/app/klass/edit/edit.component.sass (0 bytes) CREATE src/app/klass/edit/edit.component.html (19 bytes) CREATE src/app/klass/edit/edit.component.spec.ts (614 bytes) CREATE src/app/klass/edit/edit.component.ts (262 bytes) UPDATE src/app/klass/klass.module.ts (760 bytes) ``` 接着我们找到klass/add/add.component.spec.ts, 修正单元测试名称以及将`it`方法暂时修改为`fit`方法,并在终端中执行`ng test`命令来启动单元测试。 klass/add/add.component.spec.ts ``` import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { EditComponent } from './edit.component'; describe('klass EditComponent', () => { let component: EditComponent; let fixture: ComponentFixture<EditComponent>; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ EditComponent ] }) .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(EditComponent); component = fixture.componentInstance; fixture.detectChanges(); }); fit('should create', () => { expect(component).toBeTruthy(); }); }); ``` ![](https://img.kancloud.cn/aa/f4/aaf48426db353480a48d9bf02e9524f0_195x58.png) 在上个小节中,我们直接定义了两个FormControl并直接绑定到了V层中。但V层中的表单中的字段较多时,就使用C层中有大量的表单变量,这与面象对象中的“封装性”不相符。在angular中,我们可以将FormControl封装到FormGroup中,然后将FormGroup绑定到form。这样一来,CV层便建立起了如下关系: ![](https://img.kancloud.cn/b4/6c/b46c55a1f70ebe3ef99b3872557d0d99_528x240.png) ## C层初始化 FormGroup的使用也非常的简单: klass/edit/edit.component.ts ``` import {Component, OnInit} from '@angular/core'; import {FormControl, FormGroup} from '@angular/forms'; @Component({ selector: 'app-edit', templateUrl: './edit.component.html', styleUrls: ['./edit.component.sass'] }) export class EditComponent implements OnInit { formGroup: FormGroup; ➊ constructor() { } ngOnInit() { this.formGroup = new FormGroup({ ➋ name: new FormControl(), ➌ teacherId: new FormControl() ➌ }); } } ``` * ➊ 声明变量 * ➋ 初始化,构造函数中接收的类型为`{}` * ➌ 该对象中有两个属性,分别为name和teacherId,分别使用FormControl进行初始化,在初始化的过程中可以对该项赋值。 ## V层初始化 klass/edit/edit.component.spec.ts ``` <h3>编辑班级</h3> <form (ngSubmit)="onSubmit()" [formGroup]="formGroup"➊ > <label for="name">名称:<input id="name" type="text" formControlName="name"➋/></label> <label for="teacherId">教师ID:<input type="number" id="teacherId" formControlName="teacherId"➋></label> <button>更新</button> </form> ``` * ➊ 使用`[formGroup]`将表单绑定到C层的`formGroup`变量 * ➋ 使用`formControlName`来指定该input对应的formGroup中的属性 ### 测试 FormGroup同样属于ReactiveFormsModule,则测试文件如下: klass/edit/edit.component.spec.ts ```js beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [EditComponent], imports: [ ReactiveFormsModule ① ] }) .compileComponents(); })); ``` ![](https://img.kancloud.cn/94/62/946242607c14cf30b16e45d3626403f8_455x92.png) ## 设置FormGroup中的值 除在初始化的过程中过FormGroup中的项赋值以后,我们还可以调用FormGroup的setValue方法来进行赋值操作。 比如当前我们对组件进行如下的初始化操作: klass/edit/edit.component.ts ``` export class EditComponent implements OnInit { formGroup: FormGroup; private url: string; ① constructor(private route: ActivatedRoute, private router: Router, private httpClient: HttpClient) { } private getUrl(): string { ② return this.url; } /** * 加载要编辑的班级数据 */ loadData(): void { this.httpClient.get(this.getUrl()) .subscribe((klass: Klass) => { this.formGroup.setValue({name: klass.name, teacherId: klass.teacher.id}) ➊; }, () => { console.error(`${this.getUrl()}请求发生错误`); }); } ngOnInit() { this.formGroup = new FormGroup({ name: new FormControl(), teacherId: new FormControl() }); this.route.params.subscribe((param: { id: number }) => { this.setUrlById(param.id); this.loadData(); }); } /** * 用户提交时执行的更新操作 */ onSubmit(): void { } /** * 设置URL请求信息 * @param {number} id 班级ID */ private setUrlById(id: number): void { ③ this.url = `http://localhost:8080/Klass/${id}`; } } ``` * ➊ 调用FormGroup的`setValue({})`来进行赋值操作。 ## 获取FormGroup的值 在数据提交时,需要获取FormGroup的值,此时我们调用其`value`属性。 klass/edit/edit.component.ts ```ts /** * 用户提交时执行的更新操作 */ onSubmit(): void { const data = { name: this.formGroup.value.name, ➊ teacher: {id: this.formGroup.value.teacherId} ➊ }; this.httpClient.put(this.getUrl(), data) .subscribe(() => { this.router.navigateByUrl('', {relativeTo: this.route}); }, () => { console.error(`在${this.getUrl()}上的PUT请求发生错误`); }); } ``` * ➊ 调用FormGroup的value属性获取当前表单的值 # 参考文档 | 名称 | 链接 | 预计学习时长(分) | | --- | --- | --- | | 源码地址 | [https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step3.4.1](https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step3.4.1) | - | | 把表单控件分组 | [https://www.angular.cn/guide/reactive-forms#grouping-form-controls](https://www.angular.cn/guide/reactive-forms#grouping-form-controls) | 10 | | FormControlName | [https://www.angular.cn/api/forms/FormControlName](https://www.angular.cn/api/forms/FormControlName) | - | | FormGroup | [https://www.angular.cn/api/forms/FormGroup](https://www.angular.cn/api/forms/FormGroup) | - |