I am having problem accesssing products array located inside opticanOrders
which is inside orderForm
. In the console, I see that in order to access products array, I should reference it like that:
orderForm.controls.opticianOrders.controls.products.controls
But it doesn't work.
This is my component:
constructor(private customerService: CustomerService, private fb: FormBuilder) { }
orderForm: FormGroup;
ngOnInit() {
this.orderForm = this.fb.group({
name: [''],
surName: [''],
opticianOrders: this.fb.group({
orderDescription: [''],
products: this.fb.array([
this.initProduct()
])
}),
});
}
save(model: Customer) {
// call API to save customer
console.log(model);
}
onCancel(form: NgForm){
this.createState.emit(false);
}
initProduct(){
return this.fb.group({
name: [''],
manufacturerName: ['']
})
}
addProduct(){
const control = <FormArray>this.orderForm.controls['products'];
control.push(this.initProduct());
}
removeProduct(i: number){
const control = <FormArray>this.orderForm.controls['products']
}
Html
<form [formGroup]="orderForm" novalidate (ngSubmit)="save(orderForm)">
<!-- name -->
<div class="form-group">
<label>Name</label>
<input type="text" formControlName="name">
</div>
<!-- surName -->
<div class="form-group">
<label>Last Name</label>
<input type="text" formControlName="surName">
</div>
<div formGroupName="opticianOrders" class="form-group">
<label>Order Description</label>
<input type="text" formControlName="orderDescription">
</div>
<div formArrayName="products">
<div *ngFor="let product of orderForm.controls.opticianOrders.controls.products.controls; let i=index">
<div>
<span>Address {{i + 1}}</span>
<span *ngIf="orderForm.controls.opticianOrders.controls.products.controls.length > 1"
(click)="removeProduct(i)">
</span>
</div>
<div [formGroupName]="i">
<div>
<label>Product name</label>
<input type="text" formControlName="name">
</div>
</div>
</div>
</div>
<button type="submit" [disabled]="!orderForm.valid">Submit</button>
</form>
Your stackblitz code does not work. You did not import the ReactiveFormsModule
and you implemented the forms code in the hello.component.ts
also you put the template code in the app.component.html
.
See my working sample on stackblitz. It let you add (click on Add) and remove (click on 'x') products from your FormArray
.
Form value with two products:
{
name: 'John',
surName: 'Doe',
opticianOrders: {
orderDescription: '1234',
products: [
{ name: 'Cookies', manufacturerName: '' },
{ name: 'More Cookies', manufacturerName: '' }
]
}
}
For typescript this.orderForm.controls.opticianOrders
is an AbstractControl
which has no controls
property. You have to cast it to a FormGroup
first. Same with products
, you have to cast it to a FormArray
.
removeProduct(i: number){
const aFormGroup = this.orderForm.controls.opticianOrders as FormGroup;
const aFormArray = aFormGroup.controls.products as FormArray;
aFormArray.removeAt(i);
}