Reputation: 81
Spent almost a day now and learned a lot about Angular Reactive forms but still my question unanswered I am simply building a list of items with edit button on each items. Once edit button clicked that item name and description will be able to edit and submit. Simple and works fine. Now I want to add sub item to that item so I have add button which will add form array to that item form group and add sub item. That works but problem is when I click on other Item same subItem is added there too. Looks like I am not specifically adding sub item to the item which I click the edit button on. Here how I am adding sub item
buildItemsForm() {
this.itemForm = this.fb.group({
Description: [''],
ItemCode: ['']
Variations: this.fb.array([])
});
}
addVariationToItem() {
const variationsControl = this.itemForm.get('Variations') as FormArray; // here i need to specify the specific item
variationsControl.push(this.itemVariation());
}
itemVariation() {
return this.fb.group({
color: ['']
})}
This is the result
{
Description: 'this is description'
ItemCode: '123'
Variations:[
color:'red' ] // Added Here
}
{
Description: 'this is description2'
ItemCode: '789'
Variations:[
color:'red' ] // But Adding it here too
}
Update: Here is the html. I am getting items from backend response which is looped to render list of items then within the items each form is rendered so I don't think I need to change my top form to FromArray unless I have design my code wrong.
<div *ngFor="let item of items; let i = index" class="card">
<div class="item-info" *ngIf="!closeInEditItem(item)">
<div>Description : {{item.Description}}</div>
<div>Item Code : {{item.ItemCode}}</div>
<div>Variation:</div>
<button (click)="editItem(item)">Edit</button></div>
<div class="form-group" *ngIf="editSate && itemToEdit.Id == item.Id">
<form (ngSubmit)="updateItem(item)" [formGroup]="itemForm">
<textarea matInput type="text" class="form-control" placeholder="Edit Description"
formControlName="Description"></textarea>
<input matInput type="text" class="form-control" placeholder="Edit Item Code" formControlName="ItemCode">
<div formArrayName="Variations">
<div *ngFor="let variationItem of itemForm.controls['Variations'].controls; let i=index">
<input type="text" placeholder="Add Color Variation" formControlName="color">
</div>
</div>
</form>
</div>
</div>
Upvotes: 0
Views: 1596
Reputation: 783
In your case there needs to be another formArray at the top, and inside that you can have your formGroup, so the coed should be like this:-
buildItemsFormGroup() {
this.itemForm = this.fb.group({ itemArray: this.fb.array([]) });
this.buildItemFormArray();
}
buildItemFormArray() { // this method needs to be called for total number of items
const itemArray = this.itemForm.get('itemArray') as FormArray;
itemArray.push(this.fb.group({
Description: [''],
ItemCode: [''],
Variations: this.fb.array([])
}))
}
addVariationToItem(index: number) { // item index needs to be passed in which subitem has to be added.
const itemArray = this.itemForm.get('itemArray') as FormArray;
const variationsControl = itemArray.get(String(index)).get('Variations') as FormArray;
variationsControl.push(this.itemVariation()); // other controls can be pushed here.
}
itemVariation() {
return this.fb.group({
color: ['']
});
}
<form [formGroup]="itemForm">
<div *ngFor="let itemDetail of itemForm.get('itemArray')['controls']; let i=index" formArrayName="itemArray">
<div [formGroupName]="i">
<div class="item-info">
<input type= "text" formControlName="Description"> <br>
<input type="text" formControlName="ItemCode">
<div *ngFor="let variation of itemDetail.get('Variations')['controls']; let inIndex=index"
formArrayName="Variations">
<div [formGroupName]="inIndex">
<input type="text" formControlName = "color"> <!--All other controls to be added here-->
</div>
</div>
</div>
</div>
<button (click)="addVariationToItem(i)">Add Color Variation</button>
</div>
</form>
Upvotes: 2
Reputation: 57919
If you push an object, the object must be different. You code musk work, but I put an example that not work
**NOT work**
model=this.fb.group({
color: ['']
}
addVariationToItem() {
const variationsControl = this.itemForm.get('Variations') as FormArray;
//we are adding the same object
variationsControl.push(this.model);
}
But, repeat, your code must work, because you use a function that return a FormGroup, see your code in stackblitz, check the .html
Upvotes: 0
Reputation: 119
You are using one form group and reference it at more than one place. You will need another form array at the top level. It would look like “descriptions” which is a FromArray containing description form groups. And you can locate them based on id to add for each sub array. This article might help:https://alligator.io/angular/reactive-forms-formarray-dynamic-fields/
Upvotes: 1