Reputation: 936
im working with angular reactive form but having some issues while passing the formGroup
data from parent to child component.
here is the error that im getting
[96msrc/app/invoice-form/invoice-form.component.html[0m:[93m3[0m:[93m103[0m
- [91merror[0m[90m TS2740: [0mType 'AbstractControl' is missing the following properties from type 'FormGroup': controls, registerControl, addControl, removeControl, and 3 more.
[7m3[0m <app-form-item *ngFor = "let formItem of getInvoiceItem.controls; let i = index" [indexId] = "i" [invoiceFormItem] = "formItem" > [7m [0m [91m
[96msrc/app/invoice-form/invoice-form.component.ts[0m:[93m9[0m:[93m16[0m [7m9[0m templateUrl: './invoice-form.component.html', [7m [0m [96m ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~[0m Error occurs in the template of component InvoiceFormComponent.
Parent Component
import { Component, OnInit } from '@angular/core';
import { FormArray, FormControl, FormGroup } from '@angular/forms';
import { FormItemComponent } from './form-item/form-item.component';
@Component({
selector: 'app-invoice-form',
templateUrl: './invoice-form.component.html',
styleUrls: ['./invoice-form.component.css']
})
export class InvoiceFormComponent implements OnInit {
public invoiceFormItems: FormGroup = new FormGroup({
item:new FormControl(''),
quantity:new FormControl(''),
price:new FormControl(''),
total:new FormControl(''),
});
constructor() { }
ngOnInit(): void {
this.createInvoiceItemForm();
}
public createInvoiceItemForm(): void
{
this.invoiceFormItems = new FormGroup({
items : new FormArray([
FormItemComponent.addInvoiceItem(),
FormItemComponent.addInvoiceItem(),
])
});
}
get getInvoiceItem():FormArray {
return this.invoiceFormItems?.get('items') as FormArray;
}
public submitInvoiceForm()
{
}
public addNewInvoiceItems()
{
this.getInvoiceItem.push(FormItemComponent.addInvoiceItem());
}
}
Parent Component html template
<form class="form " class="mt-2" autocomplete="off" [formGroup]="invoiceFormItems" (ngSubmit)="submitInvoiceForm()">
<app-form-item *ngFor = "let formItem of getInvoiceItem.controls; let i = index" [indexId] = "i" [invoiceFormItem] = "formItem" >
</app-form-item>
<div class="form-group">
<div class="col p-0">
<button class="btn btn-primary" type="submit" (click)="addNewInvoiceItems()" [disabled]="!invoiceFormItems.valid"><i class="bx bx-plus"></i>
Add
</button>
</div>
</div>
<button type="submit">Submit</button>
</form>
Child Component
import { Component, Input } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
@Component({
selector: 'app-form-item',
templateUrl: './form-item.component.html',
styleUrls: ['./form-item.component.css']
})
export class FormItemComponent {
@Input() public invoiceFormItem: FormGroup = new FormGroup({
item: new FormControl(''),
quantity: new FormControl(''),
price: new FormControl(''),
total: new FormControl('')
});
constructor() { }
static addInvoiceItem(): FormGroup {
return new FormGroup({
item: new FormControl(''),
quantity: new FormControl(''),
price: new FormControl(''),
total: new FormControl('')
});
}
}
Child html template
<div [formGroup] = "invoiceFormItem" >
<div class="mt-4">
<div class="row justify-content-between">
<div class="col-md-2 col-sm-12 form-group">
<label for="item-name">Item</label>
<input type="txt" class="form-control" id="item-name" name="item" formControlName="item" placeholder="Enter Item">
</div>
<div class="col-md-2 col-sm-12 form-group">
<label for="quantity">Quantity</label>
<input type="number" class="form-control" id="quantity" name ="quantity" formControlName="quantity" placeholder="Enter Quantity">
</div>
<div class="col-md-2 col-sm-12 form-group">
<label for="price">Price</label>
<input type="number" class="form-control" id="price" name ="price" formControlName="price" placeholder="Item Price">
</div>
<div class="col-md-2 col-sm-12 form-group">
<label for="total">Total</label>
<input type="number" class="form-control" id="total" name ="total" formControlName="total" placeholder="Item Total Amount">
</div>
<div class="col-md-2 col-sm-12 form-group d-flex align-items-center pt-4">
<button class="btn btn-danger" type="button"> <i class="fa fa-trash"></i>
</button>
</div>
</div>
<hr>
</div>
</div>
The problem is I cant bind custom property to pass down the data(FormGroup) here
<app-form-item *ngFor = "let formItem of getInvoiceItem.controls; let i = index" [invoiceFormItem] = "formItem" >
</app-form-item>
Why is that error is occurring while binding the custom property for the child component, am i doing anything wrong? Any help will be really appreciated. Thanks
Upvotes: 0
Views: 912
Reputation: 58099
Angular (really typescript) has no idea about your "formItem", the only is create a function like
getGroup(index){
return (this.invoiceFormItems.get('items') as FormArray)
.at(index) as FormGroup
}
An pass like
<app-form-item *ngFor = "let formItem of getInvoiceItem.controls;
let i = index" [indexId] = "i" [invoiceFormItem] = "getGroup(i)">
Upvotes: 1