Угловая проверка реактивной формы с динамически именованными элементами управления
В моем приложении Angular 7 с использованием реактивных форм я создаю input
элементы на основе *ngFor
цикл, поэтому я получаю вход с динамическим именем:
<nav class="level" *ngFor="let work of workLeft">
<input [formControlName]="work.abbrev">
что, конечно, работает нормально, но сейчас я пытаюсь добавить сообщения об ошибках проверки в форму, но я не уверен, как "адресовать" элемент. Например, div обычно выглядит так:
<div *ngIf="name.errors.required">
но у меня нет name
там, как это динамическое work.abbrev
значение. Какой правильный способ справиться с этим?
Вы можете увидеть мою попытку здесь: https://stackblitz.com/edit/angular-8zevc1
1 ответ
Я предлагаю использовать FormArray
за это. С FormArray
Вот как будет выглядеть ваша реализация:
Для класса компонентов:
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>
Вот пример StackBlitz для вашей ссылки.
PS: я сделал несколько обновлений для StackBlitz, которыми вы поделились, включая вещи, которые Angular Style Guide рекомендует вместе с реальным решением. Надеюсь, это поможет.