Search code examples
arraysangulartypescriptangular-reactive-formsstrong-typing

How to patch form array in typed angular reactive forms


I am trying to figure out how to patch form array in a typed reactive Angular form. patchValue and setValue does not work in my mind consistently with FormControl for example. Here is a form

 this.form = fb.group<IPersonForm>({
      name: new FormControl<string | null>('bob'),
      phones: new FormArray<FormGroup<IPhoneForm>>([]),
    });

I can patch name control easily enough:

this.form.controls.name.patchValue('Jim', { onlySelf: true, emitEvent: false });

But form array is a challenge. Say I create a replacemenmt array

const myPhone = this.fb.group<IPhoneForm>({
      phone: new FormControl<string | null | undefined>('bob')
    });
const array = new FormArray<FormGroup<IPhoneForm>>([myPhone]);

Now if I try to patch (or set), neither compiles:

    //this.form.controls.phones.setValue(array);
    //this.form.controls.phones.setValue(array.controls);
    //this.form.controls.phones.patchValue(array);
    //this.form.controls.phones.patchValue(array.controls);

I can use setControl, but that method does not have an option for onlySelf:

this.form.setControl('phones', array, { emitEvent: false });

I feel like onlySelf is needed there because if I am replacing the data and have complex validations, I do not want them to run on any control until entire form is patched. Thank you!

Here is a stackblitz with a demo: https://stackblitz.com/edit/angular-path-typed-array?file=src%2Fmain.ts


Solution

  • you should pass the logical value, not another form to the patch

    this.form.controls.phones.patchValue([{phone: '123'}]);
    

    or

    this.form.patchValue({phones: [{phone: '123'}]})
    

    also possible to do in one call with the name at the same time

    this.form.patchValue({name: 'Jim', phones: [{phone: '123'}]})
    

    you can add onlySelf or emitEvent if you want. they are both unrelated to the question.