Angular 使用动态命名控件的反应式表单验证
Angular reactive form validation with dynamically named controls
在我的 Angular 7 应用程序中,我使用反应形式创建了 input
基于 *ngFor
循环的元素,所以我最终得到一个动态命名的输入:
<nav class="level" *ngFor="let work of workLeft">
<input [formControlName]="work.abbrev">
这当然可以正常工作,但现在我正在尝试将验证错误消息添加到表单中,但我不确定如何 "address" 该项目。例如,div 通常看起来像这样:
<div *ngIf="name.errors.required">
但我那里没有 name
,因为它是动态 work.abbrev
值。处理此问题的正确方法是什么?
你可以在这里看到我的尝试:https://stackblitz.com/edit/angular-8zevc1
我建议为此使用 FormArray
。使用 FormArray
,您的实施将如下所示:
对于组件 Class:
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators, FormArray } from '@angular/forms';
export interface Data {
abbrev: string;
max: number;
}
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
workForm: FormGroup;
workLeft: any[];
constructor(private fb: FormBuilder) {}
ngOnInit () {
this.workForm = this.fb.group({
points: this.fb.array([])
});
this.fillFormArray();
}
private fakeWebserviceCall(): Data[] {
return [
{ abbrev: 'foo', max: 12 },
{ abbrev: 'bar', max: 10 }
];
}
private fillFormArray() {
this.workLeft = this.fakeWebserviceCall();
const formControlsArray = this.workLeft.map(work => this.fb.control(work.abbrev, [Validators.min(0), Validators.max(work.max)]));
formControlsArray.forEach(control => this.points.push(control));
console.log(this.workForm.value);
}
get points(): FormArray {
return <FormArray>this.workForm.get('points');
}
pointAt(index) {
return (<FormArray>this.workForm.get('points')).at(index);
}
}
并且在模板中:
<form [formGroup]="workForm">
<div formArrayName="points">
<div *ngFor="let point of points.controls; let i = index">
{{ workLeft[i].abbrev }}: <input type="number" [formControlName]="i">
<div *ngIf="pointAt(i).invalid && (pointAt(i).dirty || pointAt(i).touched)">
The field is invalid
</div>
</div>
</div>
</form>
这里有一个 Sample StackBlitz 供您参考。
PS: 我对您分享的 StackBlitz 进行了一些更新,包括 Angular 风格指南推荐的内容以及实际解决方案。希望对您有所帮助。
在我的 Angular 7 应用程序中,我使用反应形式创建了 input
基于 *ngFor
循环的元素,所以我最终得到一个动态命名的输入:
<nav class="level" *ngFor="let work of workLeft">
<input [formControlName]="work.abbrev">
这当然可以正常工作,但现在我正在尝试将验证错误消息添加到表单中,但我不确定如何 "address" 该项目。例如,div 通常看起来像这样:
<div *ngIf="name.errors.required">
但我那里没有 name
,因为它是动态 work.abbrev
值。处理此问题的正确方法是什么?
你可以在这里看到我的尝试:https://stackblitz.com/edit/angular-8zevc1
我建议为此使用 FormArray
。使用 FormArray
,您的实施将如下所示:
对于组件 Class:
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators, FormArray } from '@angular/forms';
export interface Data {
abbrev: string;
max: number;
}
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
workForm: FormGroup;
workLeft: any[];
constructor(private fb: FormBuilder) {}
ngOnInit () {
this.workForm = this.fb.group({
points: this.fb.array([])
});
this.fillFormArray();
}
private fakeWebserviceCall(): Data[] {
return [
{ abbrev: 'foo', max: 12 },
{ abbrev: 'bar', max: 10 }
];
}
private fillFormArray() {
this.workLeft = this.fakeWebserviceCall();
const formControlsArray = this.workLeft.map(work => this.fb.control(work.abbrev, [Validators.min(0), Validators.max(work.max)]));
formControlsArray.forEach(control => this.points.push(control));
console.log(this.workForm.value);
}
get points(): FormArray {
return <FormArray>this.workForm.get('points');
}
pointAt(index) {
return (<FormArray>this.workForm.get('points')).at(index);
}
}
并且在模板中:
<form [formGroup]="workForm">
<div formArrayName="points">
<div *ngFor="let point of points.controls; let i = index">
{{ workLeft[i].abbrev }}: <input type="number" [formControlName]="i">
<div *ngIf="pointAt(i).invalid && (pointAt(i).dirty || pointAt(i).touched)">
The field is invalid
</div>
</div>
</div>
</form>
这里有一个 Sample StackBlitz 供您参考。
PS: 我对您分享的 StackBlitz 进行了一些更新,包括 Angular 风格指南推荐的内容以及实际解决方案。希望对您有所帮助。