Angular FormArray 显示验证错误
Angular FormArray display validation errors
我有 Angular 在 FormBuilder 的帮助下构建的表单。
Form 包含一个 FormArray,它具有用户想要的任意多的字段。我为字段设置了验证器
this.fb.array([this.fb.control('', Validators.required)])
并且对于每个新的 push
验证器都是相同的。
问题是我不知道如何访问特定字段的 isValid
属性,因为它们通过 [formControlName]="index"
.[=20 与 FormControl
绑定=]
我试过这样做,但似乎行不通
<div *ngIf="array.at(index).invalid" class="alert alert-danger p-2">
</div>
其中 array
是从父级传递的 formArray.controls
。
更新#1
FormGroup class 有一个 get 方法,它 returns 给定键的 abstractControl。您在 formControlName.
中使用的那个
此处是两个 Api 文档的链接:
AbstractControl
FormGroup
<form [formGroup]="form">
<input formControlName="name" type="text" />
<div *ngIf="form.get('name').invalid">
<p><Message you like to show/p>
</div>
</form>
我真的不认为这完全可以在模板上实现。这是因为要访问模板中 FormArray 的控件状态,您必须访问 this.formGroup.get('features').controls[i].invalid
。但是由于 get
return 是类型 AbstractControl
的实例,您将无法访问其上的 controls
数组。为此,您必须将 return 从 this.formGroup.get('features')
编辑的内容转换为 FormArray
。而且我真的不认为这在模板上是可能的。
您必须在 class 中创建一个方法,该方法 return 控件的有效性基于索引。
因此,如果我们继续参考您的 stackblitz,例如,方法如下:
<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>
在你的class中:
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);
}
}
更新
几个月前,我意识到在其中一种数据绑定语法(即字符串插值 - {{ ... }}
、属性 绑定 - [propertyName]="methodName()"
或属性绑定中调用方法- [class.class-name]="methodName()"
或 [style.styleName]="methodName()"
) 就性能而言成本极高。
因此,您应该使用:
{{ formGroup.controls['features'].controls[index].invalid }}
而不是:
{{ getValidity(index) }}
Here's an Updated Working Sample StackBlitz for your ref.
如果您想了解更多信息,我强烈建议您查看此主题:
希望这对您有所帮助:)
在 ngFor 语句中,您正在定义变量 "feature" 以用于表单数组的每个控件。
*ngFor="let feature of features.controls; let index = index; let last = last"
您可以使用该变量来获取该控件的无效状态。
feature.invalid
另外
当您使用响应式表单时,您不需要 HTML 中的 required 属性。
所以这个
<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">
您应该使用表单控件来快速实现这一目标。
<div *ngIf="formGroup.get('features').controls[i].controls.index.invalid && (formGroup.get('features').controls[i].controls.index.dirty || formGroup.get('features').controls[i].controls.index.touched)" class="text-center error">
<p [hidden]="!formGroup.get('features').controls[i].controls.index.errors.required">Index is required.</p>
</div>
如上答案使用
feature.invalid
from features.controls
让您一次验证该控件内的所有元素。
但是,如果您想验证特定元素,您可以使用以下代码:
> feature.controls.controlname.invalid
注意:我使用的是功能而不是功能
我在angular8中有这个例子。
执行此操作时在您的模板中。
<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.get('percentage').hasError('required')
使用 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);
}
正在向用户打印错误消息
<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>
我有 Angular 在 FormBuilder 的帮助下构建的表单。
Form 包含一个 FormArray,它具有用户想要的任意多的字段。我为字段设置了验证器
this.fb.array([this.fb.control('', Validators.required)])
并且对于每个新的 push
验证器都是相同的。
问题是我不知道如何访问特定字段的 isValid
属性,因为它们通过 [formControlName]="index"
.[=20 与 FormControl
绑定=]
我试过这样做,但似乎行不通
<div *ngIf="array.at(index).invalid" class="alert alert-danger p-2">
</div>
其中 array
是从父级传递的 formArray.controls
。
更新#1
FormGroup class 有一个 get 方法,它 returns 给定键的 abstractControl。您在 formControlName.
中使用的那个此处是两个 Api 文档的链接:
AbstractControl
FormGroup
<form [formGroup]="form">
<input formControlName="name" type="text" />
<div *ngIf="form.get('name').invalid">
<p><Message you like to show/p>
</div>
</form>
我真的不认为这完全可以在模板上实现。这是因为要访问模板中 FormArray 的控件状态,您必须访问 this.formGroup.get('features').controls[i].invalid
。但是由于 get
return 是类型 AbstractControl
的实例,您将无法访问其上的 controls
数组。为此,您必须将 return 从 this.formGroup.get('features')
编辑的内容转换为 FormArray
。而且我真的不认为这在模板上是可能的。
您必须在 class 中创建一个方法,该方法 return 控件的有效性基于索引。
因此,如果我们继续参考您的 stackblitz,例如,方法如下:
<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>
在你的class中:
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);
}
}
更新
几个月前,我意识到在其中一种数据绑定语法(即字符串插值 - {{ ... }}
、属性 绑定 - [propertyName]="methodName()"
或属性绑定中调用方法- [class.class-name]="methodName()"
或 [style.styleName]="methodName()"
) 就性能而言成本极高。
因此,您应该使用:
{{ formGroup.controls['features'].controls[index].invalid }}
而不是:
{{ getValidity(index) }}
Here's an Updated Working Sample StackBlitz for your ref.
如果您想了解更多信息,我强烈建议您查看此主题:
希望这对您有所帮助:)
在 ngFor 语句中,您正在定义变量 "feature" 以用于表单数组的每个控件。
*ngFor="let feature of features.controls; let index = index; let last = last"
您可以使用该变量来获取该控件的无效状态。
feature.invalid
另外
当您使用响应式表单时,您不需要 HTML 中的 required 属性。
所以这个
<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">
您应该使用表单控件来快速实现这一目标。
<div *ngIf="formGroup.get('features').controls[i].controls.index.invalid && (formGroup.get('features').controls[i].controls.index.dirty || formGroup.get('features').controls[i].controls.index.touched)" class="text-center error">
<p [hidden]="!formGroup.get('features').controls[i].controls.index.errors.required">Index is required.</p>
</div>
如上答案使用
feature.invalid
fromfeatures.controls
让您一次验证该控件内的所有元素。
但是,如果您想验证特定元素,您可以使用以下代码:
> feature.controls.controlname.invalid
注意:我使用的是功能而不是功能
我在angular8中有这个例子。
执行此操作时在您的模板中。
<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.get('percentage').hasError('required')
使用 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);
}
正在向用户打印错误消息
<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>