Alright, let me start with describing the problem I am actually trying to solve.
I need my form model to have the this structure:
{
nested: {
first: 'one',
second: 'two',
third: 'three',
forth: 'four', ...
}, ...
}
The child properties will be added to the model dynamically based on the users input, and the number of nested levels can vary.
The implementation looks something like this:
Initialize form:
ngOnInit() {
this.form = this.fb.group({
nested: this.getControls() // of type FormGroup
});
}
Load controls:
getControls(): FormGroup {
let group: FormGroup = new FormGroup({});
Object.keys(this.controls).forEach((key) => {
let control: FormControl = new FormControl(this.controls[key]);
group.addControl(key, control);
})
return group
}
Template with *ngFor:
<div *ngFor="let control of form.get('nested').controls | keys; let i = index">
<label>{{ getLabel(i) }}</label>
<input [attr.placeholder]="control.value">
</div>
With an add new control method:
addControl(key, value) {
let control: FormControl = new FormControl(value)
this.form.get('nested').addControl(key, control);
this.cdf.detectChanges();
}
A stripped down implementation available on Plunkr
Now, the problem I have is that the values updates for the model but the template is not re-rendering with the added inputs.
I have tried to force the change detection to fire but it has not worked.
I understand that using FormArray
provides more dynamic features, but it produces an output as this:
{
nested: [
{ first: 'one' },
{ second: 'two' },
{ third: 'three' },
{ forth: 'four' }, ...
], ...
}
Which brings us back to source of the problem.
Of course, I could utilize a function which transform back the model to the desired format before I push it on to the database, but given that the model could have several different properties at different levels in the tree, whereas for some I might be displayed as arrays and some might not, things can easily get overly complex.
Which leaves me with FormGroup
, but then how do I make sure the template renders as new input is applied? Thanks!