继Angular学习笔记49:响应式表单验证(同步)之后,有时候会遇到这样的情况:
例如有三个属性:name,age,address,分别三个控件,有一个单选按钮,来控制用户输入哪一种输入属性。
创建一个分情况显示的表单
wujiayudeMacBook-Pro:demo-test wjy$ ng g c ModifyValidator
CREATE src/app/modify-validator/modify-validator.component.less (0 bytes)
CREATE src/app/modify-validator/modify-validator.component.html (35 bytes)
CREATE src/app/modify-validator/modify-validator.component.spec.ts (692 bytes)
CREATE src/app/modify-validator/modify-validator.component.ts (309 bytes)
UPDATE src/app/app.module.ts (2161 bytes)
修改app组件的模版文件
<app-modify-validator></app-modify-validator>
在modify-validator组件中创建一个分情况显示的表单
修改模版文件:
<nz-divider [nzText]="'动态修改响应式表单的校验器'"></nz-divider>
<form nz-form [formGroup]="validateForm">
<nz-form-item>
<nz-form-label nzSpan="4" nz-col>类别</nz-form-label>
<nz-form-control nzSpan="12" nz-col>
<nz-radio-group formControlName="category">
<label nz-radio nzValue="name">name类别</label>
<label nz-radio nzValue="age">age类别</label>
<label nz-radio nzValue="address">地址类别</label>
</nz-radio-group>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="4" nz-col>name类别</nz-form-label>
<nz-form-control nzSpan="12" nz-col>
<input nz-input formControlName="name" name="name" placeholder="请输入name">
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="4" nz-col>age类别</nz-form-label>
<nz-form-control nzSpan="12" nz-col>
<input nz-input formControlName="age" name="age" placeholder="请输入age">
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="4" nz-col>地址类别</nz-form-label>
<nz-form-control nzSpan="12" nz-col>
<input nz-input formControlName="address" name="address" placeholder="请输入地址">
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="4" nz-col>表单是否有效</nz-form-label>
<nz-form-control nzSpan="12" nz-col>
{{validateForm.valid}}
</nz-form-control>
</nz-form-item>
</form>
修改类文件:
import {Component, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
@Component({
selector: 'app-modify-validator',
templateUrl: './modify-validator.component.html',
styleUrls: ['./modify-validator.component.less']
})
export class ModifyValidatorComponent implements OnInit {
public validateForm: FormGroup;
constructor(private fb: FormBuilder) {
this.validateForm = this.fb.group({
category: [null, [Validators.required]],
name: [null, [Validators.required]],
age: [null, [Validators.required]],
address: [null, [Validators.required]],
});
}
ngOnInit() {
}
}
保存,页面如下:
此时name,age,address这三个属性都是有必须填的校验器。而此时要做的就是在用户点击类别的时候,点击哪一个,哪一个必填,其他的就不用必填了。
为“类别”的单选控件增加一个检测事件。
// 通过category选中的选项分别进行处理
public handleCategoryChange(category: string): void {
switch (category) {
case 'name':
this.validateForm.get('name').setValidators([Validators.required]);
this.validateForm.get('age').clearValidators();
this.validateForm.get('address').clearValidators();
break;
case 'age':
this.validateForm.get('name').clearValidators();
this.validateForm.get('age').setValidators([Validators.required]);
this.validateForm.get('address').clearValidators();
break;
case 'address':
this.validateForm.get('name').clearValidators();
this.validateForm.get('age').clearValidators();
this.validateForm.get('address').setValidators([Validators.required]);
break;
default:
break;
}
this.validateForm.updateValueAndValidity();
}
并在constructor中增加validateForm的状态变更的订阅事件。
constructor(private fb: FormBuilder) {
this.validateForm = this.fb.group({
category: [null, [Validators.required]],
name: [null, [Validators.required]],
age: [null, [Validators.required]],
address: [null, [Validators.required]],
});
this.validateForm.statusChanges.subscribe(status => {
console.log(status);
console.log(this.validateForm);
});
}
保存,选择name,然后在name属性中输入以后,这个表单就是有效了。但是实际情况,表单的状态并不是有效。
分析原因发现,表单中的age、address实例的状态是"INVALID"(无效的),但是看到age,adddress这两个实例的校验器已经清除了。但是表单的状态却没有更新。
解决方案1: 单独更新每一个实例
修改handleCategoryChange()方法
public handleCategoryChange(category: string): void {
switch (category) {
case 'name':
this.validateForm.get('name').setValidators([Validators.required]);
this.validateForm.get('age').clearValidators();
this.validateForm.get('address').clearValidators();
break;
case 'age':
this.validateForm.get('name').clearValidators();
this.validateForm.get('age').setValidators([Validators.required]);
this.validateForm.get('address').clearValidators();
break;
case 'address':
this.validateForm.get('name').clearValidators();
this.validateForm.get('age').clearValidators();
this.validateForm.get('address').setValidators([Validators.required]);
break;
default:
break;
}
this.validateForm.get('name').updateValueAndValidity();
this.validateForm.get('age').updateValueAndValidity();
this.validateForm.get('address').updateValueAndValidity();
}
保存以后,发现解决了上述问题。
此时,在选择了name以后,其他的两个实例已经进行了更新,并在表单中更新了状态。
解决方案1: 更新所有实例,刷新状态
修改handleCategoryChange()方法
public handleCategoryChange(category: string): void {
switch (category) {
case 'name':
this.validateForm.get('name').setValidators([Validators.required]);
this.validateForm.get('age').clearValidators();
this.validateForm.get('address').clearValidators();
break;
case 'age':
this.validateForm.get('name').clearValidators();
this.validateForm.get('age').setValidators([Validators.required]);
this.validateForm.get('address').clearValidators();
break;
case 'address':
this.validateForm.get('name').clearValidators();
this.validateForm.get('age').clearValidators();
this.validateForm.get('address').setValidators([Validators.required]);
break;
default:
break;
}
this.validateForm.updateValueAndValidity();
this.validateForm.enable();
}
更新了表单中的实例校验器以后,然后通过enable()方法,根据值和校验器重新计算状态。从而达到了更新状态的目的。