Angular dynamic forms: ng-switch approach
Creating angular dynamic forms using the ng-switch approach

Nowadays forms are a crucial part of every application over the web, a signup/sign-in process, a payment process, a survey and an endless kinds of scenarios in our day to day life exploring the web.
Sometimes creating web applications goes way beyond the static and predefined forms, and there are some scenarios where having a dynamic way to create forms based on changing business requirements comes really handy in order to reduce the amount of time and resources spent supporting an application.
Some great examples of this are survey monkey or google forms, where they create their forms dynamically only using a configuration created by the user.
Angular approaches
Template driven vs Model Driven
Angular offers two approaches for handling input data using forms, you can opt for using Template Driven Forms or Model Driven Forms.
In simple words
- Template Driven forms: They are less explicit, all the form is configured over the template. If you have some basic requirements this is the way to go. Pros:It’s the simplest way to add forms into an angular applications, comes really handy for creating simple forms like such an email signup form. Cons: Don’t scale very well, and can become a little messy as an application grows.
- Model Driven Forms: They are used for more robust applications, providing a most scalable, reusable and testable approach as most of the logic is in the component. Pros: Already mentioned, more scalable, reusable and testable with a low-level API access. Cons: More verbose.
So as you may guess, the approach we are taking for our use case will be the Model Driven Approach also known as Reactive Approach. For more information about angular forms, make sure to take a look to the official angular forms docs
Getting Started
Create a new project using ng new dynamic-forms
and then navigate to the dynamic-forms folder.
If you are using the latest version of the angular-cli it will ask you if you want to add routing, for this project I selected no
and what kind of stylesheet format do you want to use for which I selected sass
. So that will create a basic angular project for us to get started. ng serve
should get us up and running. More info about the @angular/cli can be found here.
Creating our dynamic-form component
This component will be our wrapper for dynamically creating our form. So to do that simply generate a new component using angular-cli command ng generate component
ng generate component components/dynamic-form
That will create a new component for us and now we can make use of it, for now let’s replace our app.component.html content with our new created component, that’s <app-dynamic-form> </app-dynamic-form>
Now we have our basic project structure, it’s time to move ahead with our logic for creating a dynamic form.
First of all let’s define our form data model using an interface. Let’s say for instance that our data model will be the following:
This will help us to type our mock data in order to keep it consistent with our defined model. In our real world use case this will type the server seed data which will dynamically create our form.
For our use case we will be using Angular Reactive Form approach, so in order to do that we need to add the following imports into our app.module.ts.
Full documentation for angular reactive forms can be found here
This will help us with all the API required for using reactive forms, in our case we will be using FormGroup and FormControl to keep things simple.
From the official angular docs.
- FormControl: “Tracks the value and validation status of an individual form control.”
- FormGroup: “Tracks the same values and status for a collection of form controls.”
Let’s get to our dynamic-form component, so the first thing we need to do is to create our basic form. As the previous definition says, in order to track values and status for a collection of form controls AKA inputs we need to create a new instance of a FormGroup in our component.
This will be for now our DynamicForm component. We’ve just imported FormGroup in order to create a FormGroup instance for our dynamic form. This way we can tie up our template form with the logic of our component, and the way to tie these two together is by using the [FormGroup] attribute binding in our template, passing our form: FormGroup
created in our component as follows.
By doing this now we have a direct connection between our form in the template and the logic behind it in our component.
Mock Data
Everything so good so far, things are becoming more interesting. For our use case we will be using some mock data in order to recreate some kind of data fetching from a remote location — lets say an API —
So we will have some mock data based on the FormData interface defined previously. This basically will provide us the basic information for every of our form fields like the name, placeholder, type, validators, etc.
To make things simple we will import our mock data into our app.component.ts
and then pass it down to our dynamic-form component as an @Input().
So we created an instance of a MockForm object. Following next we will be accepting an @Input() formData
of type FormData[].
Then, we are accepting the data mockForm instance in our dynamic-form template
In a real world scenario, this data should be retrieved from an external API or something similar.
Now we have our data available in our component, the next step is to create the FormGroup with each of the FormControl’s or form fields that our dynamic form will have. That will take place in our ngOnInit lifecycle hook.
We have just simply looped through the formData, and created a new FormControl for every form field in the array. Then we instantiate a new FormGroup using those FormControls to keep track of them.
The only thing missing now is to track every form field in our form template by using the already created FormGroup instance.
Using ngSwitch
Now we need a way for dynamically create our template, the most simple approach for this is using the ngSwitch directive. First of all we need to loop over the formData in order to get access to every formData element. And next just switch over every controlType to get to know what kind of input we need to display on the UI.
ControlType was just a generic name, you can use whatever name you want to define for the properties of your dynamic form.
As we are already looping through the data, the next step to follow is to ask for what kind of input do we want to display on the UI.
By using ngSwitchCase we can validate what kind of control type we have as an element in the loop run. In the first case let’s handle the scenario where we have an input of type ‘text’.
First of all we need to bind the controlName into the formControName in order to point to our previously created FormControl instance. Note that we are using the controlName property of our data as we previously did in the creation of the FormGroup instance in our component. This is a MUST in order to tie up the template inputs with the form fields instances.
Then we just bound type and name attributes with the valueType and controlName data properties respectively. Finally for the sake of simplicity we bound the basic validations into our input template. This also could have been done in the component when we were creating our FormGroup instance. It’s just matter of personal preference.
And last but not least, we are handling error use cases based on the validity of the form. You can learn more about form error and validations here.
We can do the same for allowing another input types like ‘radio’ and ‘selects’ in our case this will be the template for creating both of them.
And with this, we have all in order to dynamically render our form based on some mock data. The following codesandbox is a running example of our use case.
This way you can power up your applications for creating dynamic content , in this case a forms use case with a really straightforward approach.
We’ve just scratched the surface, and using this simple starter guide will help you to cover more complex scenarios like, custom validations, adding custom inputs, predefined values, etc. It just takes a really good understanding of how form approach works on angular and start playing with all the alternatives that the @angular/forms API provides. You can refer to the Reactive Forms, Template Forms, Forms Validation & Dynamic Forms official documentation.
You can check the full source code on Github
I’m looking for a new gig. Strong experience working on highly dynamic applications using both angular and recatjs. Dms open on X formerly twitter @camilogiraldo