Я пытаюсь описать проблему на примере ( полный пример на stackblitz )
Если я пытаюсь поместить некоторые части реактивной формы в виде простых "formControls""или" formGroups "с дочерними компонентами, проблем нет.(См. Пример на стекаблице выше).FormGroupDirective
работает как положено.
Но если я попытаюсь поместить FormArray в дочерний компонент, у меня возникнут проблемы из-за:
<div [formGroupName]="i">
<!--
Error: formGroupName must be used
with a parent formGroup directive.
-->
<div>
Реактивная форма - это простая форма:
ngOnInit () {
this.newForm = this.fb.group({
id: [{value: '4711', disabled: this.idReadOnly}, Validators.required],
chapter: this.fb.group({
name: ['Some Chapter', Validators.required]
}),
faq: this.fb.array(this.faqArray)
});
}
Как уже упоминалось выше, с id
и chapter
проблем нет, они реализованы в пользовательских дочерних компонентах, таких как:
<fe-input
[controlPath]="['id']"
placeholder="Child-FormControl ID"
></fe-input>
<my-form-group
[controlPath]="['chapter', 'name']"
placeholder="Child-FormGroup Chapter"
[required]="true"
>
</my-form-group>
В приложении на stackblitz вы увидитерабочие части "ID" и "Глава".
Тот же самый подход с formArray
:
<my-form-array
[controlPath]="['faq']"
placeholder="Child-FormArray FAQ"
[required]="true"
></my-form-array>
должен работать, как и ожидалось, но часть <div [formGroupName]="i">
вызывает только в пределахдочерний компонент вышеупомянутая ошибка выше:
Error: formGroupName must be used
with a parent formGroup directive.
Если я использую это в исходном файле (где определяется реактивная форма), он работает без проблем.
Яперепутал, может я просто упустил из виду простую проблему?Кто-нибудь может мне помочь?Весь пример доступен здесь: ( >> stackblitz )
UPDATE 1:
Я интегрировал решение из @yurzui с
viewProviders: [{
provide: ControlContainer,
useExisting: FormGroupDirective
}]
и ошибка "Error: formGroupName must be used..
" исчезла.После этого я интегрировал пользовательский компонент для полей formArray, и они не могут получить значение элемента управления.Я думаю, что я близок к решению.Это пользовательский компонент:
import { Component, OnInit, Input } from '@angular/core';
import {
FormControl,
FormGroupDirective
} from '@angular/forms';
@Component({
selector: 'fe-input',
template: `
<mat-form-field>
<input
matInput
[placeholder]="placeholder"
[formControl]="control"
[required]="required"
/>
<mat-error>
This is a required field!
</mat-error>
</mat-form-field>
`,
styles: [
]
})
export class FormElementInputComponent implements OnInit {
// Values to be set:
@Input() controlPath: any;
@Input() placeholder: string;
@Input() controlValue: any;
@Input() required = false;
// That's the reuseable control
control: FormControl;
constructor(private fgd: FormGroupDirective) {}
ngOnInit() {
this.control = this.fgd.control.get(
this.controlPath
) as FormControl;
}
}
И, наконец, это часть шаблона my-form-array
:
template: `
<div fxLayout="column">
<div *ngFor="let c of control.controls; index as i">
<div [formGroupName]="i">
<fe-input
[controlPath]="q"
placeholder="Question"
[required]="required"
></fe-input>
<fe-input
[controlPath]="a"
placeholder="Answer"
[required]="required"
></fe-input>
<div>
</div>
</div>
`,