How to Use Angular FormArray(s) within FormGroup(s) In Reactive Forms
Are you trying to use a FormArray on a dynamic/reactive Angular Form, but it is not working? This should help you solve your problem.
Start by setting up a new project:
ng new [name your project]
Then create the component:
ng g component [component name]
You should now see something like this:
Next, let’s add the required modules in your app.module.ts file:
Make sure to add FormsModule and ReactiveFormsModule to your imports.
Now let’s create our initial form. Here I will be using FormBuilder.
While adding a getter for your FormsArray is optional, I highly recommend it.
Now your [component].component.ts file should look like this:
Now we can work on the display side. Update your [component].component.html view to look like this:
Note the [formGroup] field with the name of the formGroup: companyForm. To access anything within this form, you will want to use formControlName instead of [(ngModel)] with the name of that control (e.g., companyName).
Let’s run the app.
ng serve
Now let’s add the FormArray to the display.
If you refresh the view, you won’t see anything because there is nothing in the array. Let’s update the view and the component to allow the adding of some data.
Note that we added another form: adminForm. This is what each object within the admins FormArray will look like. You can add any validations to that object specifically right here.
Refresh the page. You should now see the [Add] button. Press it a few times to see what addNewAdmin() does.
It looks great, but if you look at the Developer Console, you will see this:
ERROR 11.g core.js:6498 ERROR Error: Cannot find control with name: 'name' at _throwError (forms.js:1782) at setUpControl (forms.js:1562) at FormGroupDirective.addControl (forms.js:5347) at FormControlName._setUpControl (forms.js:5929) at FormControlName.ngOnChanges (forms.js:5874) at FormControlName.rememberChangeHistoryAndInvokeOnChangesHook (core.js:1510) at callHook (core.js:2548) at callHooks (core.js:2507) at executeInitAndCheckHooks (core.js:2458) at refreshView (core.js:9499)
Don’t worry, we can fix this.
First, we have to tell Angular that this is a FormArray, and that it has a name.
If you run it now, you will still find an error in the console.
core.js:6498 ERROR Error: Cannot find control with path: 'admins -> name' at _throwError (forms.js:1782) at setUpControl (forms.js:1562) at FormGroupDirective.addControl (forms.js:5347) at FormControlName._setUpControl (forms.js:5929) at FormControlName.ngOnChanges (forms.js:5874) at FormControlName.rememberChangeHistoryAndInvokeOnChangesHook (core.js:1510) at callHook (core.js:2548) at callHooks (core.js:2507) at executeInitAndCheckHooks (core.js:2458) at refreshView (core.js:9499)
Online searches led me to define my [formGroup] like we did with the main form.
But this may result in a compile error:
error TS2740: Type 'AbstractControl' is missing the following properties from type 'FormGroup': controls, registerControl, addControl, removeControl, and 3 more.
You can remedy this by setting strictTemplates to “false” in your tsconfig.json file.
But I find that a less than ideal solution. Instead, do this:
You can bind the model to the formGroupName and use the index instead. To be honest, I am not sure why this is working, but it is working and doesn’t throw any errors. And in this case, that is good enough for me.
I hope this helped and saved you some time. Here is the complete Component Code.