Getting All FormControls Inside An NgForm

Sometimes Angular can be a real headache when it comes to some really basic use cases, especially when form building.

Case and point, I recently had to get all controls within a ngForm so that I could run a custom method on them. At first, I figured that something like so would suffice :

let myControls = myNgForm.form.controls; //<-- This should get all controls right?

But actually this only returns the name of the inner controls, but not the control object itself. Luckily, there is a simple way to then get the control based on the name using a for loop :

for(const field in myNgForm.form.controls) {
    const control = myNgForm.form.get(field); //This gets the actual formControl. 
}

This works perfectly and our control variable is now set to the actual AbstractControl object (Which we can then cast to a FormControl/Group/Form etc if we need to).

There’s one more step we need to do though. The problem with this is that I don’t want to have to copy and paste all of this around my code base. So let’s make it reusable!

The first thing we need to do is create a file called ng-form.extensions.ts, hopefully in an extensions folder, somewhere in our project. Inside of it, we want the following :

import {  AbstractControl, NgForm } from '@angular/forms';

declare module "@angular/forms/" {
    interface NgForm {
      getAllControls(this:Form) : AbstractControl[];
    }
}
NgForm.prototype.getAllControls = function(this:NgForm) {
    let controls : AbstractControl[] = [];
    for(const field in this.form.controls) {
        const control = this.form.get(field);
        controls.push(control);
    }
    return controls;
}

If you haven’t seen this type of code before, it’s how we can add “extension” methods to existing interfaces from Angular. What we are doing here is essentially telling Typescript that NgForm actually has another method called “getAllControls” available to it, that returns an array of AbstractControl.

Anywhere we want to use this, we can simply add an import to the top of whatever file :

import 'src/app/_core/extensions/ng-form.extensions'; //Obviously this is the actual location of your extensions file

And then use it like any other method in your component :

this.myForm.getAllControls();

Nice and easy! And super re-usable. The best thing is that you can add more and more extensions to your NgForm any time you feel there is something missing from the default behaviour, and you don’t need to create all sorts of complex services that take an NgForm parameter, you can add it directly onto the interface itself!

Leave a Reply

Your email address will not be published. Required fields are marked *