Angular 2: valueChanges后更新FormControl验证器

25

有没有一种方法可以更新 FormControl 对象的 Validators?我有一个 FormGroup,在其中一个 Input 是 select 字段时,当 select 字段的值发生变化时,我想让我的 FormGroup 中的其他 FormControl 更改验证器。

这是我的 FormGroup 组件中的 subscribeToFormChanges() 方法:

private appIdRegexes = {
    ios: /^[a-zA-Z][a-zA-Z0-9]*(\.[a-zA-Z0-9\-]+){2,}$/,
    android: /^([a-zA-Z])[a-zA-Z0-9_]*(\.[a-zA-Z][a-zA-Z0-9\-]*){2,}$/,
    any: /^any$/
  };

private subscribeToFormChanges(): void {
    const myFormValueChanges$ = this.appsForm.valueChanges;
    myFormValueChanges$.subscribe(x => {
      const platform = this.appsForm.controls['platform'].value;
      const appId = this.appsForm.controls['appId'].value;

      if (this.appIdRegexes[platform]) {
        this.appsForm.controls['appId'] = new FormControl(appId, Validators.pattern(this.appIdRegexes[platform].source));
      }
    });
  }

这是HTML模板:

<div class="row" [formGroup]="appsForm">
  <div class="form-group col-xs-6">
    <label>Platform</label>

    <select id="licensePlatform" class="form-control"
            formControlName="platform">
      <option *ngFor="let platform of licensePlatforms" [value]="platform">
        {{platform}}
      </option>
    </select>

    <small [hidden]="appsForm.controls.platform.valid">
      Platform is required
    </small>
  </div>

  <div class="form-goup col-xs-6">
    <label>App ID</label>
    <input type="text" class="form-control" formControlName="appId">
    <small [hidden]="appsForm.controls.appId.valid">
      Please use the right ID format
    </small>
  </div>
</div>

当我像这里展示的实现subscribeToFormChanges()方法时,当写入输入字段时appsForm.controls.appId.value不再更新。最初值是更新的。


使用patch value来更新表单 this.form.patchValue({controlTobeUpdated:value}); https://angular.io/docs/ts/latest/api/forms/index/FormGroup-class.html#!#patchValue-anchor - Manish
@user32 但是 patchValue() 只允许我更新值 - 而不是验证器? - Markus Török
对的,patchValue() 允许您更新值,但一旦该值被更新,验证器将会触发。 - Manish
现在我明白你的问题了,我之前是在建议其他的事情。 - Manish
3个回答

18

我通过监听平台选择字段上的valueChanges,然后使用setValidators() 方法在appId输入字段上解决了这个问题。这篇文章非常有帮助。

这是我的解决方案:

 private subscribePlatformChanges() {
    const platformCtrl = this.appsForm.controls['platform'];
    const changes$ = platformCtrl.valueChanges;

    changes$.subscribe(platform => {
      this.appsForm.controls['appId'].setValidators([Validators.pattern(this.appIdRegexes[platform].source),
                                                    Validators.required]);
      this.appsForm.controls['appId'].updateValueAndValidity();
    });
  }

以下文章展示了三种实现相同目的的方法:https://netbasal.com/three-ways-to-dynamically-alter-your-form-validation-in-angular-e5fd15f1e946 - Chris Tapay

5
要重新检查FormGroup中的控件,您可以使用FormControlupdateValueAndValidity。如果this.appsForm确实是一个FormGroup
this.appsForm.controls.forEach(control => control.updateValueAndValidity());

我认为这只更新了验证状态,但没有更新验证器正则表达式模式? - Markus Török

0

您可以通过以下方式从选择器中触发更改事件

<select id="licensePlatform" class="form-control"
            formControlName="platform"  (change)="update($event.target.value)" >
      <option selected="selected" disabled="disabled" value="">Select Card Type</option>
      <option *ngFor="let platform of licensePlatforms" [value]="platform" >
        {{platform}}
      </option>
    </select>

在组件中,您可以编写以下更新函数:

update(value){
      if(value){
        (<FormControl>this.appsForm.controls['platform']).setValue(value, {onlySelf: false});
        const appId = this.appsForm.controls['appId'].value;
        if (this.appIdRegexes[value]) {
        this.appsForm.controls['appId'] = new FormControl(appId, Validators.pattern(this.appIdRegexes[value].source));
      }
    };

  }

这将根据您在下拉菜单中所做的选择更新验证器。 我相信这将解决您的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接