FormArray patchValue in model-driven forms

1,132 views
Skip to first unread message

Steve Gatsios

unread,
Jan 12, 2017, 2:32:13 PM1/12/17
to Angular

My question and it has been bugging me for a while is :
How can I use patchValue in FormArray when I dont know in advance the size of the array and how many controls to push.

Pete Bacon Darwin

unread,
Jan 12, 2017, 2:35:01 PM1/12/17
to Angular
Yes, I have being having the same problem. I have solved it with a few helper functions:

/**
 * Attach a factory function to a FormArray so that we can automatically create child controls inside `setValues()`
 */
export function setChildControlFactory(control: FormArray, factory: () => AbstractControl) {
  (control as any).__createChildControl = factory;
}

function createChildControl(control: FormArray) {
  return (control as any).__createChildControl();
}

/**
 * Recursively set the values of a form control, creating new children FormArrays as necessary
 */
export function setValues(control: AbstractControl, value: any) {
  if (control instanceof FormGroup) {
    if (value != null) {
      Object.keys(value).forEach(name => {
        if (control.contains(name)) {
          setValues(control.get(name), value[name]);
        }
      });
    }
  } else if (control instanceof FormArray) {
    const length = value ? value.length : 0;
    // Remove excess controls from the array
    while (control.length > length) {
      control.removeAt(control.length - 1);
    }
    // Add missing controls
    while (control.length < length) {
      control.push(createChildControl(control));
    }
    // Update all the values in the array
    for (let i = 0; i < length; ++i) {
      setValues(control.at(i), value[i]);
    }
  } else {
    control.setValue(value);
  }
}

To use it you must identify the FormArray objects in your form and set the child control factory for each:

  private createForm() {
    this.sessionForm = new FormGroup({
      name: new FormControl(),
      students: this.studentArray = new FormArray([])
    });
    // Student controls are simple form controls
    setChildControlFactory(this.studentArray, () => new FormControl());
  }
Reply all
Reply to author
Forward
0 new messages