Reputation: 2945
I am trying to dynamically create a nested FormArray in my Angular 6 application.
I have a quote, which has a collection of quote-items
export class Quote {
quoteId: number;
quoteItems: QuoteItem[]
status: string;
}
export class QuoteItem {
quoteItemId: number;
description: string;
quoteItemDetails: QuoteItemDetail[]
}
export class QuoteItemDetail {
quoteItemDetailId: number;
rate: number;
quantity: number;
total: number;
}
I have a form that has the Quote object, where a user can click on a button to add and remove one or more QuoteItems.
This is my code where I initialise my form:
ngOnInit() {
this.quoteForm = this.fb.group({
status: [''],
quoteItems: this.fb.array([])
});
this.addQuoteItem();
}
And this is how I get the dynamic adding and removing working:
get quoteItems() {
return this.quoteForm.get('quoteItems') as FormArray;
}
addQuoteItem() {
this.quoteItems.push(this.fb.group({
description: '',
quoteItemDetails: this.fb.array([])
}));
}
removeQuoteV2Item(index) {
this.quoteV2Items.removeAt(index);
}
And my html:
<div formArrayName="quoteItems">
<div @items *ngFor="let item of quoteItems.controls; let contentIndex=index" [formGroupName]="contentIndex">
<input type="text" formControlName="description">
</div>
</div>
<p>
<a (click)="addQuoteItem()">Add Quote Item</a>
</p>
What I'm trying to do is then have the same functionality but for my QuoteItemDetail array. So a user can add one or more quoteItems, and within them add one or more QuoteItemDetails.
I'm really stuck at the first point, I can't work out how to get a form array assessor, this doesn't work as an example, as I'm not sure how to pass the index across:
get quoteItemDetails() {
return this.quoteItems.get('quoteItemDetails') as FormArray;
}
Upvotes: 0
Views: 104
Reputation: 1485
You will not be able to do it with an accessor. The accessor is going to give you a reference to one attribute. But as you said, in this case you need an index to specify what quoteItemDetails FormArray reference you need (since as far as I understand you want a FormArray in each quoteItem, so each quoteItem can have several quoteItemDetails, right?).
I don't see a problem with that though. Instead of doing it with an accessor like you have done with the quoteItems, you will have to do it with a method taking the one parameter you need, the index. Something like this:
quoteItemDetails(quoteItemIndex: number): FormArray {
return this.quoteItems.at(quoteItemIndex).get('quoteItemDetails') as FormArray;
}
And then you represent it on the template:
<div formArrayName="quoteItems">
<div @items *ngFor="let item of quoteItems.controls; let contentIndex=index" [formGroupName]="contentIndex">
<input type="text" formControlName="description">
<div *ngFor="let quoteItemDetail of quoteItemDetails(contentIndex).controls; let detailIndex=index" [formArrayName]="detailIndex">
<input type="number" formControlName="description" />
</div>
</div>
</div>
I hope this helps you. I have not tested the code but the solution should be someshere along these lines.
Upvotes: 1