Reputation: 622
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>
Upvotes: 1
Views: 2423
Reputation: 3850
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);
}
Upvotes: 0
Reputation: 638
Please replace your HTML Code as per below
<form [formGroup]="orderForm" (ngSubmit)="save()">
<!-- 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 class="form-group">
<label>Order Description</label>
<input type="text" formControlName="orderDescription">
</div>
<div formArrayName="products">
<div *ngFor="let product of orderForm.controls.products['controls']; let i=index">
<div>
<span><strong>Product {{i + 1}}</strong></span>
<span class="fa fa-times" *ngIf="orderForm.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>
<label>Product Manufacturer name</label>
<input type="text" formControlName="manufacturerName">
</div>
</div>
</div>
<div class="margin-20">
<a (click)="addProduct()" style="cursor: pointer; text-transform: uppercase; font-weight: 500">
Add another Entry +
</a>
</div>
</div>
<button class="btn btn-primary" type="submit" [disabled]="orderForm.invalid">Submit</button>
</form>
Please replace TS code as per below. I have used a trick in save form method, check whether it works for you or not?
constructor(private fb: FormBuilder) { }
orderForm: FormGroup;
ngOnInit() {
this.orderForm = this.fb.group({
name: ['', Validators.required],
surName: ['', Validators.required],
orderDescription: ['', Validators.required],
products: this.fb.array([
this.initProduct()
])
});
}
save() {
console.log(this.orderForm.value);
const obj = {
name: this.orderForm.value.name,
surName: this.orderForm.value.surName,
orderDescription: this.orderForm.value.orderDescription,
opticianOrders: {
products: this.orderForm.value.products
},
};
console.log(obj);
}
initProduct() {
return this.fb.group({
name: ['', Validators.required],
manufacturerName: ['', Validators.required]
})
}
addProduct() {
const control = <FormArray>this.orderForm.controls['products'];
control.push(this.initProduct());
}
removeProduct(i: number) {
const control = <FormArray>this.orderForm.controls['products'];
control.removeAt(i);
}
Upvotes: 2