How to get index of changed element in angular forms array

I am using Angular 4 with reactive forms. I have an array of form that I am trying to associate with an array that I am tracking in my component. I use reactive forms, so I can get confirmation, so I do not want to use the template form approach.

I add elements to the form array as follows:

createFormWithModel() { this.orderForm = this.fb.group({ orderNumber: [this.order.ProductBookingOrder], orderDate: [this.order.PurchaseOrderIssuedDate], lineDetailsArray: this.fb.array([]) }) const arrayControl = <FormArray>this.orderForm.controls['lineDetailsArray']; this.order.ProductBookingDetails.forEach(item => { let newGroup = this.fb.group({ ProductName: [item.ProductName], Quantity: [item.ProductQuantity.Quantity], UOM: [item.ProductQuantity.UOM], RequestedShipDate: [item.RequestedShipDate] }) }) } 

The order form is obviously my reactive FormGroup forms. an order is my object that I receive from my API, and I want to update its values, including row data. I think I should use "valueChanges.subscribe" for each new group, but I'm not sure how to get the index of the item that has been changed. Any thoughts?

  newGroup.valueChanges.subscribe('i want value and index some how' => { this.order.ProductbookingDetails[index].ProductName = value.ProductName; }); 

Here is the HTML for this part:

 <tbody formArrayName="lineDetailsArray"> <tr [formGroupName]="i" *ngFor="let line of orderForm.controls['lineDetailsArray'].controls; index as i"> <td><input class="form-control" type="text" placeholder="Product Name" formControlName="ProductName" required/></td> <td><input class="form-control" type="number" step=".01" (focus)="$event.target.select()" placeholder="Quantity" formControlName="Quantity"/></td> <td><input class="form-control" readonly formControlName="UOM"></td> <td><date-picker formControlName="RequestedShipDate" format="L" [showClearButton]="false"></date-picker></td> <td><button type="button" (click)="deleteLineDetail(i)">Remove</button></td> </tr> </tbody> 
+8
source share
3 answers

I would not use valueChanges here, it would be launched excessively, especially if the array has many values.

You can have a change event for each value and just pass the value and index, something like

 (keyup)="changeValue(line.controls.ProductName.value, i)" 

But this species is fighting for the goal of the reactive form.

Despite the fact that you have many values ​​that you don’t want to show on the form, and these are values ​​that the user cannot change, I would just add them to the form anyway as form controls, nothing says what you need to show them in the template!

Thus, if you create the form in such a way that it matches your order model, you could simply directly assign the form value to your model when submitting. I highly recommend this approach.

+6
source
 export class CustomFormArray { public form: FormGroup; public get someArray(): FormArray { return this.form.get('someArray') as FormArray } constructor(private _fb: FormBuilder) { this.form = _fb.group({ someArray: _fb.array([]) }); this.someArray.controls.forEach( control => { control.valueChanges.subscribe( () => { console.log(this.someArray.controls.indexOf(control)) // logs index of changed item in form array } ) } ) } } 
+4
source

You can create your own component for the elements you want to keep in your array of forms. For each update, deletion, etc. You are passing the event to the parent component and the index that you can emit with the event you are binding in the parent component, or you have the index in the parent component in the template to use as an additional input parameter for the function that you use to bind to a child component change event.

Read this article and you will understand what I mean:

https://medium.com/spektrakel-blog/angular2-building-nested-reactive-forms-7978ecd145e4

0
source

Source: https://habr.com/ru/post/1269808/


All Articles