Reactive Forms: How to add new FormGroup or FormAr

2020-01-27 08:28发布

问题:

In the other examples at StackOverflow there are many questions about using FormGroups in FormArrays. But my question is the opposite.

FormArrays have a push method, that makes many things possible. FormGroups have indeed an addControl method for adding simple FormControls. Afaik FormGroups do not have addFormArray or addFormGroup method. Therefore I need your help.

Following situation:

this.myForm = this.fb.group({
  id: this.fb.control([this.book.id]),
  // or short form `id: [this.book.id],`
});

Adding a simple control at a later point in time is easy:

this.myForm.addControl('isbn', this.fb.control(this.book.isbn));

But what about adding FormArrays and FormGroups into an existing FormGroup? For instance, I would like to use the following array and object for this purpose:

const authors  = ['George Michael', 'Aretha Franklin'];
const metaData = { description : 'Great Book', publication: 2019}

I would like to add authorsArray or metaData only then if they are existing. That's the reason, why I want to add them at a later time.

p.s. Please ignore the validation rules.

回答1:

FormGroup addControl method accepts AbstractControl as parameter which can be either a FormControl or a FormArray or another FormGroup as they all extend AbstractControl.

class FormGroup extends AbstractControl
...
class FormControl extends AbstractControl
...
class FormArray extends AbstractControl

FormBuilder can help you building such controls with array() and group() methods:

this.myForm = this.fb.group({
  id: this.fb.control([this.book.id]),
  authors: this.fb.array(['George Michael', 'Aretha Franklin']),
  metaData: this.fb.group({ description : 'Great Book', publication: 2019})
});

You still can use the factory afterwards to build the controls you need (no matter what kind of control it is):

this.myForm.addControl('authors', this.fb.array(['George Michael', 'Aretha Franklin']))
this.myForm.addControl('metaData', this.fb.group({ description : 'Great Book', publication: 2019}))


回答2:

You can simply pass the FormArray instead of a FormControl.

this.form.addControl('arr',this.fb.array([]));

Edit: To use existing value

To use the value from the authors array, use this:

authors.forEach(author => {
  (<FormArray>this.form.controls.arr).push(new FormControl(author));
});

OR

this.myForm.addControl('authors', this.fb.array(['George Michael', 'Aretha Franklin']))