Angular FormArray显示验证错误

时间:2018-08-31 20:49:35

标签: angular forms typescript validation angular2-form-validation

我有在FormBuilder的帮助下构建的Angular表单。

Form包含一个FormArray,它具有用户想要的多个字段。我已经为字段设置了验证器

this.fb.array([this.fb.control('', Validators.required)])

,并且对于每个新的push验证器都是相同的。

问题是我不知道如何访问特定字段的isValid属性,因为它们是通过FormControl[formControlName]="index"绑定的。

我已经尝试过这样做,但是似乎不起作用

<div *ngIf="array.at(index).invalid" class="alert alert-danger p-2">
</div>

array是从父级传来的formArray.controls

更新#1

有一种情况https://stackblitz.com/edit/angular-7ppkoh

7 个答案:

答案 0 :(得分:1)

我真的不认为这完全可以在模板上实现。这是因为要访问模板中FormArray控件的状态,必须访问this.formGroup.get('features').controls[i].invalid。但是由于get返回类型为AbstractControl的实例,所以您将无法访问其上的controls数组。为此,您必须将this.formGroup.get('features')返回的所有内容转换成FormArray。而且我真的认为模板上不可能做到这一点。

您必须在您的类中创建一个方法,该方法将根据索引返回控件的有效性。

例如,如果我们继续引用您的堆叠闪电战,则方法如下:

<form [formGroup]="formGroup">
  <div formArrayName="features">
    <div 
      class="row no-gutters form-group" 
      *ngFor="let feature of features.controls; let index = index; let last = last">
      <input 
        type="text" 
        class="form-control px-2 col" 
        [formControlName]="index" 
        title="feature" 
        required>

        IS Invalid - {{ getValidity(index) }}

      <div class="col-3 col-md-2 row no-gutters">
        <button 
          class="col btn btn-outline-danger" 
          (click)="removeFeature(index)">
          -
        </button>
        <button 
          class="col btn btn-success" 
          *ngIf="last" 
          (click)="addFeature()">
          +
        </button>
      </div>
    </div>
  </div>
</form>

在您的课堂上:

import { Component } from '@angular/core';
import { FormArray, FormBuilder, FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {

  constructor(
    private fb: FormBuilder,
  ) {}

  formGroup = this.fb.group({
    features: this.fb.array([this.fb.control('', Validators.required)])
  });

  get features(): FormArray {
    return this.formGroup.get('features') as FormArray;
  }

  addFeature(): void {
    this.features.push(this.fb.control('', Validators.required));
  }

  getValidity(i) {
    return (<FormArray>this.formGroup.get('features')).controls[i].invalid;
  }

  removeFeature(index): void {
    this.features.removeAt(index);
    console.log(this.features);
  }

}

这是您推荐的StackBlitz

答案 1 :(得分:1)

在ngFor语句中,您将定义变量“ feature”用于表单数组的每个控件。

*ngFor="let feature of features.controls; let index = index; let last = last"

您可以使用该变量来获取该控件的无效状态。

feature.invalid 

这里是Stackblitz


另外

使用反应式表单时,在HTML中不需要必需的属性。

所以这个

<input type="text" class="form-control px-2 col" [formControlName]="index" title="feature" required>

可以是

<input type="text" class="form-control px-2 col" [formControlName]="index" title="feature">

答案 2 :(得分:0)

FormGroup类具有一个get方法,该方法返回给定键的abstractControl。您在formControlName中使用的那个。

以下是两个Api文档的链接:
AbstractControl
FormGroup

{
  "body": "Write a function fibonacci that takes an integer n and returns the nth number of the fibonacci sequence. DO NOT USE RECURSION. Code must run in O(n) time.",
  "solution": "function fibonacci(n) {\n\n}",
  "tests": "[typeof fibonacci === 'function', typeof fibonacci(3) === 'number', fibonacci(0) === 0, fibonacci(1) === 1, fibonacci(2) === 1, fibonacci(3) === 2, fibonacci(10) === 55, fibonacci(20) === 6765, fibonacci(40) === 102334155]",
  "testDescriptions": "[\"fibonacci should be a function\", \"fibonacci should return a number\", \"the 0th fibonacci number is 0\", \"the 1st fibonacci number is 1\", \"the 2nd fibonacci number is 1\", \"the 3rd fibonacci number is 2\", \"the 10th fibonacci number is 55\", \"the 20th fibonacci number is 6765\", \"the 40th fibonacci number is 102334155\"]",
  "title": "Fibonacci"
}

答案 3 :(得分:0)

您应该使用表单控件来实现这一目标。

a = 349

答案 4 :(得分:0)

如上答案使用

  

feature.invalid来自features.controls

让您一次验证该控件中的所有元素。

但是,如果要验证特定元素,可以执行以下代码:

> feature.controls.controlname.invalid

注意:我使用的是功能而非功能

答案 5 :(得分:0)

我在8号角有这个例子。

在模板中执行此操作。

<ng-container formArrayName="calibers">
        <ng-container *ngFor="let item of qualityForm.get('calibers')['controls']; let index = index" [formGroupName]="index.toString()">
          <ion-item>
            <ion-label position="floating">{{ getCaliberName(item) }}</ion-label>
            <ion-input formControlName="percentage" placeholder="Input Percentage" type="number" clearInput></ion-input>
            <ng-container *ngIf="item.get('percentage').hasError('required')">
              <span class="errorMsg">Input Percentage</span>
            </ng-container>
            <ng-container *ngIf="item.get('percentage').hasError('max')">
              <span class="errorMsg">Percentage cannot be greater than 100</span>
            </ng-container>
          </ion-item>
        </ng-container>
      </ng-container>

ngFor中的item对象将使您可以访问表单控件。获取数组形式错误所需要做的就是item.get('percentage').hasError('required')

答案 6 :(得分:0)

creating form with formArray.

createForm() {
    this.studentForm = this.fb.group({
      name: [],
      id: [],
      hobbies: this.fb.array([])
    })
  }

  addHobbies() {
   const control = new FormControl(null, [Validators.required]);
   (<FormArray>this.studentForm.get('hobbies')).push(control);
  }

Printing error message to user

<form [formGroup]="studentForm" (submit)="saveStudent()">
    <input type="text" id="id" name="id" formControlName="id">
    <input type="text" id="name" name="name" formControlName="name">
    <div formArrayName="hobbies">
        <label>Hobbies</label>
        <button type="button" (click)="addHobbies()">Add Hobbies</button>
        <div *ngFor="let formControl of studentForm.get('hobbies')['controls']; let i = index">
            <input type="text" [formControlName]="i"> 
            <div *ngIf="!studentForm.get('hobbies')['controls'][i].valid && 
                        studentForm.get('hobbies')['controls'][i].errors?.required">
           <p>This field is required</p>
       </div>
        </div>
    </div>
    <button type="submit">Submit Student</button>
</form>