从表单数组添加和删除表单组

时间:2019-07-09 10:51:21

标签: angular validation angular-reactive-forms formarray

我创建了一个Angular反应形式,它具有几个基本的形式控制元素,然后是简单形式组的形式数组。您可以动态地从表单数组添加和删除表单组实例。

这里是demo

动态添加新的表单组实例时,其字段是必填字段。但是,您可以将其删除。由于字段是必填字段,因此添加新表单组后,该表单立即无效。我遇到的问题是,即使您删除了表单组实例,并且每个剩余的表单控件都是有效的,该表单仍然无效。我已经检查了这一点-我遍历了所有表单元素,并且每个表单控件都有效,但是表单数组仍然无效。

从中删除无效的表单组后,如何确保表单数组有效?

组件

import { AbstractControl, FormArray, FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms';

import {Component, OnInit } from '@angular/core';

/**
 * @title Inputs in a form
 */
@Component({
  selector: 'input-form-example',
  templateUrl: 'input-form-example.html',
  styleUrls: ['input-form-example.css'],
})
export class InputFormExample implements OnInit {

  studyGuideForm: FormGroup;
  error: string = null;

  constructor(
    private fb: FormBuilder
    ) { }

    ngOnInit() {
      this.studyGuideForm = this.fb.group({
        studyGuideName: ['', Validators.required],
        description: [''],
        flashCards: this.fb.array([
          this.fb.group({
            front: ['', Validators.required],
            back: ['', Validators.required]
          })
        ], this.invalidFlashCardValidator())
      });
  }

  onSubmit() {
    if (this.studyGuideForm.valid) {
      console.log("Validation successful, can create");
      this.error = null;
    } else {
      console.log("The form is invalid, cannot submit");
      this.error = "Please enter all required fields and try again.";
    }
  }

  get flashCards() {
    return this.studyGuideForm.get('flashCards') as FormArray;
  }


  addFlashCard() {
    this.flashCards.push(this.fb.group({ front: '', back: ''}));
  }

  isRemovable() {
    return this.flashCards.length > 1;
  }

  removeFlashCard(pos: number) {
    this.flashCards.controls.splice(pos, 1);
  }

  invalidFlashCardValidator(): ValidatorFn {
    return (control: AbstractControl): {[key: string]: any} | null => {
      if (this.studyGuideForm) {
        let flashCardControls = this.flashCards.controls;
        for (const control in flashCardControls) {
          let fg = flashCardControls[control] as FormGroup;
          if (!fg.valid) {
            return {'invalidFlashCard': { value: 'Invalid flash card detected'}};
          }
        }
      }
      return null;
    }
  }

}

模板

<mat-card class="card-container">
    <h1 class="center-text">Create Study Guide</h1>
    <form [formGroup]="studyGuideForm" class="form-primary">
        <h2>Basic Information</h2>
        <mat-form-field class="full-width">
          <input matInput placeholder="Name" formControlName="studyGuideName" name="name" required>
        </mat-form-field>
        <mat-form-field class="full-width">
          <textarea matInput placeholder="Description" formControlName="description" name="description"></textarea>
        </mat-form-field>
        <div formArrayName="flashCards">
            <h2>Flash Cards</h2>
            <div *ngFor="let flashCard of flashCards.controls; index as i; first as isFirst" class="flash-card full-width" appearance="outline">
                <div [formGroupName]="i">
                    <div *ngIf="isRemovable()" class="close" (click)="removeFlashCard(i)">X</div>
                    <mat-form-field class="full-width">
                        <textarea matInput placeholder="Front" formControlName="front" name="front{{i}}" required></textarea>
                    </mat-form-field>
                    <mat-form-field class="full-width">
                        <textarea matInput placeholder="Back" formControlName="back" name="back{{i}}" (keydown.Tab)="onTab(i)" required></textarea>
                    </mat-form-field>
                </div>
            </div>
            <button mat-fab color="accent" (click)="addFlashCard()" class="add-button">+</button>
        </div>
    </form>
</mat-card>
<div class="button-container">
    <button mat-raised-button color="primary" class="big-button" (click)="onSubmit()">Submit</button>    
</div>
<p class="error-text" *ngIf="error || (error && !studyGuideForm.valid)">{{ error }} </p>

1 个答案:

答案 0 :(得分:2)

使用AbstractControlgit commit方法手动更新表单数组的有效性状态

updateValueAndValidity

基于@Eliseo的评论,更好的方法是使用FormArray removeFlashCard(pos: number) { this.flashCards.controls.splice(pos, 1); this.flashCards.updateValueAndValidity(); } 方法

removeAt()