Good Day.
I looked for the solution, and even though there are a view similar question to what I am asking, I am sure this one is a bit more unique and not a duplicate.
here is my html form:
<div class="form-group col-md-6" formGroupName="schema">
<div formArrayName="currencies">
<input type="text" class="form-control" id="percentage" formControlName="percentage" placeholder="Discount %*" required>
</div>
</div>
and here is my ts formBuilder.
this.createPromo = this.fb.group({
type: ['promotion'],
name: ['', Validators.required],
description: ['', Validators.required],
enabled: ['', Validators.required],
promotion_type: ['', Validators.required],
start: ['', Validators.required],
end: ['', Validators.required],
schema: this.fb.group({
currencies: this.fb.array([
this.fb.group({
percentage: '',
currency: 'ZAR'
})
])
}),
});
So I want my form to submit as a grouped array. However the error in the console is the following Cannot find control with path: 'schema -> currencies -> percentage'
, thus I am not able to submit my form as percentage
is empty even after I input a number.
Binding FormArray to Template Inside the div use ngFor to loop through each element of skills FormArray. let i=index will store the index value of the array in template local variable i . We will make use of it to remove the element from the skills array. Each element under the skills is a FormGroup .
The FormArray is a way to Manage collection of Form controls in Angular. The controls can be FormGroup, FormControl, or another FormArray. Because it is implemented as Array, it makes it easier dynamically add controls.
You'll need the following for your scenario:
div
with formGroupName="schema"
.div
with formArrayName="currencies"
.div
with ngFor="let currencyGroup of currencyFormGroups; let i = index;"
. Notice that currencyFormGroups
is a getter in your Component Class.div
with [formGroupName]="i"
where i
is the index that we created on the fly within *ngFor
.input
s with formControlName="percentage"
and formControlName="currency"
respectively..
Here's all these steps translated to code:
import { Component } from '@angular/core';
import { FormGroup, FormControl, FormArray, Validators, FormBuilder } from '@angular/forms';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
createPromo: FormGroup;
constructor(private fb: FormBuilder) { }
ngOnInit() {
this.createPromo = this.fb.group({
'type': ['type'],
name: ['name', Validators.required],
description: ['description', Validators.required],
enabled: ['enabled', Validators.required],
promotion_type: ['promotion_type', Validators.required],
start: ['start', Validators.required],
end: ['end', Validators.required],
schema: this.fb.group({
currencies: this.fb.array([
this.fb.group({
percentage: 'percentage',
currency: 'ZAR'
}),
this.fb.group({
percentage: 'percentage',
currency: 'INR'
}),
])
}),
});
}
get currencyFormGroups() {
return (<FormArray>(<FormGroup>this.createPromo.get('schema')).get('currencies')).controls;
}
}
Template:
<form [formGroup]="createPromo">
...
<div formGroupName="schema">
<div formArrayName="currencies">
<div *ngFor="let currencyGroup of currencyFormGroups; let i = index;">
<div [formGroupName]="i">
<input
type="text"
name="percentage"
formControlName="percentage">
<input
type="text"
name="currency"
formControlName="currency">
</div>
</div>
</div>
</div>
</form>
Here's a Sample StackBlitz for your ref.
PS: For simplicity's sake, I've considered all the form controls as input
. Please make your changes accordingly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With