Angular 4 patchValue based on index in FormArray

user1752532 picture user1752532 · May 12, 2017 · Viewed 31.5k times · Source

I am looking to update a formArray after the user adds a value in an empty created control.

Currently when the user selects to add a new item i build onto the formArray with empty values.

buildItem(item?: any, key?: any): FormGroup {
  // Item will pass undefined for initial buildItem in onLoad and new items
  let itemName: string;
  let keyValue: string;
  if (item === undefined) { 
     itemName = ''; key = '' }  
  else { 
     itemName = item.name; keyValue = key 
  };

  /**
   * Builds a single item for form group array in the collectionForm.
   */
   return this.formBuilder.group({ 
                item: [itemName || '', Validators.required], 
                properties: { item, key: key } || {} });
}

This works fine for the initial creation and the update of items that are already added. The issue is with new items that are added with empty values. When i add a new item i need to add the return key from firebase in the properties.key

In the method for the save of that new item i added a patchValue

this.items.patchValue([{ 
         // item being returned from firebase promise
         item: item.name, 
         properties: { item: item.name, key: item.$key' } 
}]);

However the patchValue is not working at all. When i try the update that new value, although the values have been saved to firebase i still get a return for the values as empty or the save values set on the initial BuildItem() and not the updated values in the patchValue

I see on the angular FormArray Documentation that

It accepts an array that matches the structure of the control, and will do its best to match the values to the correct controls in the group. REF

Does that mean that it might and might not update that value .. it will just do its best to try? I figure if i can add the index for the value that i want to patch then it should not be a issue at all. like with the removeAt(idx)

So if i can write something like

this.form.patchValue.atIndex(this.idx,[{ 
         item: item.name, 
         properties: { item: item.name, key: item.$key' } 
}];

But not sure i can do that .. well pretty sure that it not possible in that form. Is there any way to specifically target the item that gets patched in a formArray or am i maybe not understanding this correctly.

I can sort of get away with this by pushing the new value onto the formArray

this.items.push(this.buildItem(...));

however then i have to add

this.items.removeAt(this.idx); 

In order to remove the initial control on the empty build , which does not seem like any sort of good code.

Answer

developer033 picture developer033 · May 12, 2017

Use FormArray#at + AbstractControl#patchValue:

this.items.at(index).patchValue(...);