【问题标题】:Angular Form can not update Validation by a dynamic angular formAngular 表单无法通过动态角度表单更新验证
【发布时间】:2020-12-22 09:49:28
【问题描述】:

我现在有一个角度形式的问题,它无法在动态角度形式中动态更新验证。

在这个例子中,有一个select,可以选择email或者phone,在这个selector下面,有一个input field,可以是email也可以是phone number。

但问题是,如果 select 的值发生变化,验证子组件将不会更新。

代码如下:


<div *ngFor="let item of contactForm.get('information').controls; let informationIndex = index">
              <div [formGroupName]="informationIndex">
                <div fxLayout="row" class="parameterWrapper">
                  <div class="parameterLabel step">type</div>
                  <label>
                    <select class="parameterInputSelect" formControlName="type" (change)="setContactValidation($event, informationIndex, contactFormIndex)">
                      <option *ngFor="let param of getContactInformationTypes(false)" [value]="param">{{param}}</option>
                    </select>
                  </label>
                </div>
                <div fxLayout="row" class="parameterWrapper">
                  <div class="parameterLabel step">detail</div>
                  <label>
                    <input class="parameterInput" type="text" formControlName="detail" [value]="item.controls.detail">
                  </label>
                  <app-validation-errors type="detail" [control]="item.controls.detail" [selectedValue]="selectedInfoType"></app-validation-errors>
                </div>
              </div>

在这段代码中,您可以看到一个选择和一个输入字段。还有一个子组件 validate-error。

在 ts 文件中

public setContactValidation(value: any, infoIndex: number, contactFormIndex: number): void {
    this.selectedInfoType = value.target.value;
    const information = this.contactFormData.controls[contactFormIndex].get('information') as FormArray;
    let validator = [];
    switch (this.selectedInfoType) {
      case ContactInformation.TypeEnum.EMAIL:
        validator = [Validators.email];
        information.controls[infoIndex].get('detail').setValidators(validator);
        break;
      case ContactInformation.TypeEnum.PHONE:
        validator = [Validators.pattern(VALIDATORS.ONLY_NUMBER)];
        information.controls[infoIndex].get('detail').setValidators(validator);
        break;
      default:
        break;
    }
    information.controls[infoIndex].updateValueAndValidity();
  }

但是,如果我选择电子邮件,则输入字段中的验证不起作用。如果 slect 值发生更改,我如何更新子组件验证错误。

有什么解决办法吗?

【问题讨论】:

    标签: angular validation angular-forms


    【解决方案1】:

    您正在设置验证器,但没有删除旧的。

    每当您更改为电子邮件时,您都需要在设置电子邮件验证器之前删除现有的验证器。我希望你明白我的意思。

    【讨论】:

    • setValidator 将一个验证器替换为另一个,问题是在运行时添加或删除验证器时,必须调用 updateValueAndValidity() 才能使新验证生效
    【解决方案2】:

    我认为问题在于在运行时添加或删除验证器时,必须调用 updateValueAndValidity() 才能使新验证生效。

    无论如何,我建议创建一个自定义表单验证。由于取决于两个值,请记住在更改类型时使用 form.get('detail').updateValue

    <form [formGroup]="form">
      <select formControlName="type" 
              (change)="form.get('detail').updateValueAndValidity()">
        <option value="email">email</option>
        <option value="phone">phone</option>
        </select>
      <input  formControlName="detail">
      <div *ngIf="form.get('detail').errors">
         {{form.get('detail').errors|json}}
        </div>
      </form>
    
    form=new FormGroup({
        'type':new FormControl('email'),
        detail:new FormControl(null,this.validatorType())
    
      })
    
      validatorType()
      {
        return (control:FormControl)=>{
          const form=control.parent?(control.parent as FormGroup):null
          if (form)
          {
            if (form.get('type').value=='email')
              return Validators.email(control)
            else
              return Validators.pattern(/^[0-9]\d*$/)(control)
          }
         
          return null
        }
      }
    

    你可以看到stackblitz

    【讨论】:

      猜你喜欢
      • 2021-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-06
      • 2014-11-25
      • 1970-01-01
      • 2015-11-26
      相关资源
      最近更新 更多