Reputation: 917
I have the following Angular form:
<form [formGroup]="futureForm" (ngSubmit)="onSaveFuture(futureForm.value)">
// ...
<div class="row" *ngFor="let value of atr.values" >
<div class="col-md-6">
<input type="text" class="form-control form-control-sm" value="{{value.prop1}}"
formControlName="values.prop1">
</div>
<div class="col-md-3">
<input type="text" class="form-control form-control-sm" value="{{value.prop2}}"
formControlName="values.prop2">
</div>
<div class="col-md-3">
<input type="text" class="form-control form-control-sm" value="{{value.prop3}}"
formControlName="values.prop3">
</div>
</div>
// ...
</form>
Note that formGroup name is futureForm
and on submit we are calling onSaveFuture
.
My problem is that atr.values
, which is being looped through with *ngFor
, is an array. I want futureForm.value
(the parameter that gets passed to the saveFuture
function) to contain the array with value objects in it when the form gets submitted.
The following problem occurs. The console says this:
Cannot find control with name: 'values.prop1'
Also on submit, i am not getting the array that i want. atr.values
is not even an array, but a single object.
How do i make it so that my different inputs will correspond to their respective atr.values
entry so that the value is shown and also passed as an array to the onSaveFuture
function?
My component looks like this:
export class SomeComponent implements OnInit {
atr: IAtr;
futureForm;
// constructor..
ngOnInit(): void {
// ..
this.futureForm = this.formBuilder.group({
// ..
values: this.atr.values,
});
}
// onSaveFuture..
}
Is there something i am missing, or do i need to use something other than formControlName?? Thanks in advance.
Upvotes: 0
Views: 2641
Reputation: 29335
if you're data is an array, you need a FormArray
which is a little more complex than normal form groups.
ngOnInit(): void {
// ..
this.futureForm = this.formBuilder.group({
// ..
// initialize with array of groups
values: this.formBuilder.array(this.atr.values.map(v => this.getValueGroup(v))),
});
}
get valuesForm() {
return this.futureForm.get('values') as FormArray
}
private getValueGroup(v?) {
return this.formBuilder.group({
// value group properties
prop1: [v ? v.prop1 : ''] // something like this, initialize to prop value or default, add validators or whatever
})
}
addValue(v?) {
// use this to add new values
const vg = this.getValueGroup(v);
this.valuesForm.push(vg);
}
removeValue(index: number) {
// remove values
this.valuesForm.removeAt(index);
}
then in template, things will look different too:
<ng-container formGroupName="values"> <!-- need some wrapper to build the path to the array... still uses formGroupName even though array -->
<div class="row" *ngFor="let ctrl of valuesForm.controls; let i = index" [formGroupName]="i"> <!-- iterate the controls, group names are the index -->
<div class="col-md-6">
<input type="text" class="form-control form-control-sm"
formControlName="prop1"> <!-- just the property name, don't explicitly assign value -->
</div>
<div class="col-md-3">
<input type="text" class="form-control form-control-sm"
formControlName="prop2">
</div>
<div class="col-md-3">
<input type="text" class="form-control form-control-sm"
formControlName="prop3">
</div>
</div>
<ng-container>
Upvotes: 1