动态和隐藏字段的反应式表单验证

首先,我有一个角度反应表单,它有一个按钮,可以向该表单添加另一个FormArray。所有验证工作正常,并按预期工作。当向已经动态的表单组引入另一个动态控件时,事情变得有点棘手。此控件基于在另一个表单控件中所做的选择来显示/隐藏。

当控件显示时,我引入了验证,当控件隐藏时,验证被清除。这可确保我的表单保持正确有效/无效。

它的行为有点不正常,例如,当我完成一组输入并添加另一组动态输入时,两者都会触发隐藏的控件...然后修改以前的隐藏输入--形式保持不变。例如:

选择123将触发&Quot;Other Code&Quot;控件,删除该值应使表单无效,但此时它仍为真。

我为选择分配了更改功能,以确定选择了哪些内容。

      selectClick(x) {
            const f = this.form;
            let items = this.form.get('justificationItems') as FormArray;
            if (x === '123') {
                items.controls.forEach(i => {
            console.log(i)
                    i['controls'].other.setValidators([Validators.required]);
            //      i['controls'].other.updateValueAndValidity();
                });
            } else {
                items.controls.forEach(i => {
                    i['controls'].other.clearValidators();
                //  i['controls'].other.updateValueAndValidity();
                });
}
        f.updateValueAndValidity();
    }

我怀疑当将SELECT属性更改为触发上述操作时,它不会对正确的索引项执行此操作,而会对所有索引项执行此操作?

StackBlitz-https://stackblitz.com/edit/angular-prepopulate-dynamic-reactive-form-array-ufxsf9?file=src/app/app.component.ts


解决方案

清除/添加验证器的最佳方法确实是启用或禁用FormControls。请记住,Form控件的状态为以下之一:

 type FormControlStatus = 'VALID' | 'INVALID' | 'PENDING' | 'DISABLED';

这样我们就可以简单地启用/禁用FormControl。此外,我们在创建Form Group时可以将其创建为禁用,因此最初将不无效

好吧,代码有点混乱。首先使用I[‘Controls’].Other(实际上您可以使用i.controls.other与FormBuilder和新表单的陌生组合。

像往常一样,我们有一个Form数组,我们创建一个getter

  get justificationItems()
  {
    return this.form.get('justificationItems') as FormArray;
  }

代替使用两个不同的函数来创建表单,我们可以使用和唯一

  createJustificationField(x: any=null): FormGroup {
    x=x || {name:null,description:null,code:null,other:null}
    return new FormGroup({
      name: new FormControl(x.name, [Validators.required]),
      description: new FormControl(x.description, [Validators.required]),
      code: new FormControl(x.code, [Validators.required]),
      other: new FormControl({value:x.other,
                  disabled:x.code!=='123'},[Validators.required]),
    });
  }

查看我们可以用作

this.createJustificationField(..an object..)
this.createJustificationField()

我们的函数:createFormaddItemselectClick(我更喜欢另一个名称,类似于codeChange,但这是一个很小的更改),如下所示

  createForm() {
    this.service.getmodel().subscribe((response:any) => {
      this.form = new FormGroup({
        justificationItems: new FormArray(
                  response.justificationItems.map(x=>
                        this.createJustificationField(x))
        ),
      });
    });
  }

  addItem(): void {
    this.justificationItems.push(this.createJustificationField());
    this.form.updateValueAndValidity();
  }


  selectClick(x,i) {
    if (x === '123') 
      this.justificationItems.at(i).get('other').enable()
    else
      this.justificationItems.at(i).get('other').disable()
        
    this.form.updateValueAndValidity();
  }

并且.html在以下方面变得更加清晰

<form *ngIf="form" [formGroup]="form">
  <div formArrayName="justificationItems">
    <div
      *ngFor="
        let orgs of justificationItems.controls;
        let i = index;
        let last = last
      "
      [formGroupName]="i"
    >
      <label>Name </label>
      <input formControlName="name" placeholder="Item name" /><br />
      <label>Description </label>
      <input
        formControlName="description"
        placeholder="Item description"
      /><br />
      <label>Code </label>
      <select
        (change)="selectClick($event.target.value, i)"
        formControlName="code"
      >
        <option value="123">123</option>
        <option value="456">456</option></select
      ><br />
      <ng-container *ngIf="justificationItems.at(i).value.code === '123'">
        <label>Other Code </label>
        <input formControlName="other" placeholder="other" /><br /><br />
      </ng-container>
      <button
        *ngIf="last"
        [disabled]="justificationItems.at(i).invalid"
        type="button"
        (click)="addItem()"
      >
        Add Item
      </button>
    </div>
  </div>
  <button [disabled]="!form.valid" type="button">Submit</button>
</form>

<p>Is form valid: {{ form?.valid | json }}</p>

请参阅stackblitz

相关文章