Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get index of changed item in angular form array

Tags:

I'm using Angular 4 with reactive forms. I have a form array that I am trying to tie to an array I keep track of in my component. I'm using reactive forms so I can have the validation, so I don't want to use the template forms approach.

I add items to the form array like so:

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 orderForm is obviously my reactive forms FormGroup. the order is my object I get from my API and I want to update its values, including the line details. I think I should use 'valueChanges.subscribe' on each newGroup but I'm not sure how to get the index of the item that was changed. Any thoughts?

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

Here's the HTML for this portion:

<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> 
like image 746
Kevin Avatar asked Jul 13 '17 17:07

Kevin


People also ask

How do I use ValueChanges in FormArray?

The ValueChanges is an event raised by the Angular forms whenever the value of the FormControl, FormGroup or FormArray changes. It returns an observable so that you can subscribe to it. The observable gets the latest value of the control. It allows us to track changes made to the value in real-time and respond to it.

How does Angular check form control changes?

FormArray extends AbstractControl so it has valueChanges property which emits chanes. The values in subscribe will return a array with value of each input field when any of changes(grammatically or from UI). In case of if there are FormGroup in FormArray nothing changes. just use following component code.

How do you use FormArray?

First, we need to import the FormArray from the Angular Forms Module. Build a formGroup orderForm using the FormBuilder. We define items as FormArray. We need to capture two fields under each item, the name of the item & description and price.

What is setValue in Angular?

We use the SetValue to update the FormControl , FormGroup or FormArray . When we use it to update the FormGroup or FormArray the SetValue requires that the object must match the structure of the FormGroup or FormArray exactly. Otherwise, it will result in an error. Best Angular Books.


1 Answers

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

You could have a change event on each value, and just pass the value and index, something like

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

But this kind of fights the purpose of the reactive form.

Even though you have plenty of values that you do not want to show in form, and it is values that the user cannot modify, I'd just add them to the form anyway as form controls, nothing says that you need to show them in template!

This way, if you build the form in a way that it would match your model order, you could just directly assign the form value to your model upon submit. I highly recommend this approach.

like image 175
AT82 Avatar answered Oct 23 '22 07:10

AT82