Stevie Star
Stevie Star

Reputation: 2371

Angular 2 Forms - How to patchValue on a nested Form Group that contains an array of objects

I've got a form that has the ability to add/remove rows of items. Whenever I want to go to edit my form, I run an asynchronous call to grab some data then patch/set the values of the form controls accordingly. Everything works as expected, however, with my rows of items, when I utilize Angular 2's patchValue function, it only patches a form group with the first object of an array of objects, instead of all of the objects.

So for example, if my form had 3 rows of line items, like in an invoice, only the first one is being populated. Can anyone tell me what I'm doing wrong?

Here is my component functionality

constructor() {
    this.createCheckRequestForm();
}

createCheckRequestForm() {
    this.createRequestForm = this._fb.group({
      issued_date: [new Date().toISOString(), [<any>Validators.required]],
      due_date: [new Date().toISOString(), [<any>Validators.required]],
      invoice_number: ['', [<any>Validators.required]],
      how_to_send: ['Mail', [<any>Validators.required]],
      normal_processing: ['', []],
      is_corporation: ['', []],
      line_items: this._fb.array([this.initLineItem()])
    });
  }

  /**
   *  Init the line item for the form builder
   */
  initLineItem(options?) {
    return this._fb.group({
        description: ['', []],
        coding: ['', []],
        amount: ['', []],
        line_item_types: [[], []]
    });
  }


populateFormWithRequest(requestId) {
    this.formPopulationObs = this._checkRequests.getRequest(requestId).subscribe(requestData => {




      // Iterate through the line items and patch them
      let lineItems = [];
      requestData.line_items.forEach((lineItem, index) => {

        let lineItemTypes = [];
        if(lineItem.line_item_types) {
          lineItemTypes = lineItem.line_item_types;
        }

        // Separate key-store for the coding dropdown models
        this.lineItemCodings[index] = lineItem.coding;

        let lineItemObj = {
          description: lineItem.description,
          coding: lineItem.coding,
          amount: lineItem.amount,
          line_item_types: lineItemTypes,
        }
        lineItems.push(lineItemObj);
      })

      this.createRequestForm.patchValue({line_items: lineItems});
  })
}

If I have an array like this, only the first element shows up in the "patch"

[ 
 {amount: "600", coding: "-Kfxw732pfWUS5rU0TRu", description: "Cameras"},
 {amount: "600", coding: "-Kfxw732pfWUS5rU0TRu", description: "Lights"}
]

Thanks in advance!

Upvotes: 3

Views: 5396

Answers (2)

Florian D.
Florian D.

Reputation: 270

The same result, a little bit easier - without creating a empty item and overwriting it:

populateFormWithRequest(requestId) { 
  this.formPopulationObs = this._checkRequests.getRequest(requestId).subscribe(requestData => { 
    this.createRequestForm["line_items"] = 

requestData.line_items.forEach(itm=>(<FormArray>this.createRequestForm["line_items"]).push(this.createRequestForm.group(itm)));

)); 
}); 
}

Upvotes: 0

Stevie Star
Stevie Star

Reputation: 2371

Alright, so in order to get this to work, I had actually push form group array elements onto the "line_items" control that already existed THEN patch the values. Here is my updated function:

populateFormWithRequest(requestId) {
    this.formPopulationObs = this._checkRequests.getRequest(requestId).subscribe(requestData => {


      // Iterate through the line items and patch them
      requestData.line_items.forEach((lineItem, index) => {

        let lineItemTypes = [];
        if(lineItem.line_item_types) {
          lineItemTypes = lineItem.line_item_types;
        }

        // Create the item obj
        let lineItemObj = {
          description: lineItem.description,
          coding: lineItem.coding,
          amount: lineItem.amount,
          line_item_types: lineItemTypes,
        }

        const control = <FormArray>this.createRequestForm.controls['line_items'];
        control.push(this.initLineItem());
        control.at(index).patchValue(lineItemObj);
      });
  })
}

Upvotes: 4

Related Questions