教师组件支持`FormControl`后,便可以按以前的设置移除班级编辑组中的`teacherId`缓存转而使用`FormControl`了。 ## 使用FormControl 来到组件的V层,使用`[formControl]`替换原写法: ```html +++ b/first-app/src/app/clazz/edit/edit.component.html @@ -12,7 +12,7 @@ <div class="mb-3 row"> <label class="col-sm-2 col-form-label">班主任</label> <div class="col-sm-10"> - <app-klass-select [id]="teacherId" (beChange)="onTeacherChange($event)"></app-klass-select> + <app-klass-select [formControl]="formGroup.get('teacherId')"></app-klass-select> <small class="text-danger" *ngIf="teacherId === undefined"> 必须指定一个班主任 </small> ``` 启用对应的测试用例后,测试如下: ![image-20210407092849271](https://img.kancloud.cn/8c/20/8c20dcc8f0a9ce41540dbfd6334be0ea_2142x362.png) - 组件初始化时可以选中原班主任 - 选择某个班主任后点击保存按扭,控制台打印了相应的教师ID ### 另一种写法 在Angular中当把form指定为某个`FormGroup`时,也可以如下指定`FormControl`: ```html +++ b/first-app/src/app/clazz/edit/edit.component.html @@ -12,7 +12,7 @@ <div class="mb-3 row"> <label class="col-sm-2 col-form-label">班主任</label> <div class="col-sm-10"> - <app-klass-select [formControl]="formGroup.get('teacherId')"></app-klass-select> + <app-klass-select formControlName="teacherId"></app-klass-select> <small class="text-danger" *ngIf="teacherId === undefined"> 必须指定一个班主任 </small> ``` 使用`formControlName`的方式更简洁,在日后会被更多的使用。在此我们再复习一遍两种使用方式本质上传值的区别:`[formControl]="xxx"`中的`xxx`对应组件C层中的属性,而`formControlName="xxx"`中的`xxx`即是普通的字符串。 - `[a]="xxx" `中的`xxx`对应C层中的属性。 - `(a)="xxx()"`中的`xxx`对应C层中的方法。 - `a="xxx"`中的`xxx`是普通的字符串。 ### 验证提示 将验证提示同样使用`FormControl`的方式: ```html <div class="col-sm-10"> <app-klass-select formControlName="teacherId"></app-klass-select> - <small class="text-danger" *ngIf="teacherId === undefined"> + <small class="text-danger" *ngIf="formGroup.get('teacherId').invalid"> 必须指定一个班主任 </small> </div> ``` 但遗憾的是,我们并没有办法通过测试看到这个提示效果。在编程中我们应该规避写一些永远都不会用到的代码,当某些代码被确认为永远都不会起效时,则应该将其删除: ```html <div class="col-sm-10"> <app-klass-select formControlName="teacherId"></app-klass-select> - <small class="text-danger" *ngIf="formGroup.get('teacherId').invalid"> - 必须指定一个班主任 - </small> </div> ``` ## 删除冗余代码 V层中的编辑字段全部使用`FormControl`后C层中的`teacherId`便失去了意义,可以删除了: ```typescript +++ b/first-app/src/app/clazz/edit/edit.component.ts @@ -15,7 +15,7 @@ export class EditComponent implements OnInit { * 班级名称. */ nameFormControl = new FormControl('', Validators.required); - teacherId: number | undefined; + /** * 表单组,用于存放多个formControl */ @@ -45,14 +45,12 @@ export class EditComponent implements OnInit { .subscribe(clazz => { console.log('接收到了clazz', clazz); this.nameFormControl.patchValue(clazz.name); - this.teacherId = clazz.teacher.id; this.formGroup.get('teacherId')?.setValue(clazz.teacher.id); }, error => console.log(error)); } onTeacherChange($event: number): void { console.log('接收到了选择的teacherId', $event); - this.teacherId = $event; this.formGroup.get('teacherId')?.setValue($event); } ``` ## TODO 最后,还要为组件尚未完成的功能加入TODO,以防后期自己把这个未完成的功能忘掉,同时在控制台中打印警告信息,做一下提醒: ```typescript ngOnInit(): void { const id = this.activatedRoute.snapshot.params.id; - // 调用loadById方法,获取预编辑的班级 + // todo: 调用loadById方法,获取预编辑的班级 + console.log('ngOnInit方法获取路由ID及调用loadById尚未测试,请在集成测试中补充代码'); } ``` ## 本节作业 - 使用`formControlName`属性改写班级名称对应的`input`后测试 | 名称 | 链接 | | --------------- | ------------------------------------------------------------ | | FormControlName | [https://angular.cn/api/forms/FormControlName](https://angular.cn/api/forms/FormControlName) | | 本节源码 | [https://github.com/mengyunzhi/angular11-guild/archive/step6.4.6.zip](https://github.com/mengyunzhi/angular11-guild/archive/step6.4.6.zip) |