Angular学习笔记50:响应式表单动态修改表单校验器

继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() {
  }

}

保存,页面如下:

Angular学习笔记50:响应式表单动态修改表单校验器_第1张图片

此时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属性中输入以后,这个表单就是有效了。但是实际情况,表单的状态并不是有效。

Angular学习笔记50:响应式表单动态修改表单校验器_第2张图片

分析原因发现,表单中的age、address实例的状态是"INVALID"(无效的),但是看到age,adddress这两个实例的校验器已经清除了。但是表单的状态却没有更新。

Angular学习笔记50:响应式表单动态修改表单校验器_第3张图片

解决方案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();
  }

保存以后,发现解决了上述问题。

Angular学习笔记50:响应式表单动态修改表单校验器_第4张图片

此时,在选择了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()方法,根据值和校验器重新计算状态。从而达到了更新状态的目的。

你可能感兴趣的:(#,Angular)