[Angular] How to create a dynamic & reusable form

Eden Park
3 min readNov 5, 2022

Introduction

Have you encountered any situations where you have multiple forms in a similar manner? Angular included Build dynamic form section for us to tap into the concept of dynamic form to generate different versions of forms based on metadata that describes the business object model. Here in this article, I am going to show you how we can generate dynamic form boilerplates which then can be used in your enterprise-level projects.

The code can be found in StackBlitz

Without Further Adieu

Folder Structure

dynamic-form will be shared between multiple components. So we are adding this to the shared folder. Then, inside the dynamic form, we will keep adding form elements such as dropdown, checkbox, or radio button.

  1. Add a generic class for FIELD

shared/dynamic-form/models/field.ts

This generic field has common properties that are used to control the form elements.

We will also create an input field as an example, but it’s not stopping you from adding more form elements such as dropdown.

1.1 Input Field

The input field will override the fieldType as input, then we will check fieldType in the dynamic-form.component.html to generate <app-input-field>. The type will be defaulted as text and can be overwritten with number or email.

2. Create a Base Directive

This base-form.directive.ts will be used for common properties binding as shown below. Then, input, dropdown, and checkbox components will inherit this class reducing code duplications and extending base class functionalities.

3. Create Dynamic Component and Module

Specific files required can be seen in the StackBlitz . We need to create a dynamic-form.module.ts and importswhatever necessary modules to be able to render elements and then import DynamicFormModule in the app.module.ts

Then we will create dynamic form template and component as below. We will provide an array of fields and check if the fieldType is input, and then we will render InputComponent. We will pass the data from the parent component, and then will use two-way binding. The field.name should be matched with the data property to be able to use the two-way binding feature.

In the component, we will receive the events from the child components and do the required actions.

Sort Pipe will be used to sort the elements based on the priority field. For example, the field having priority value 0 will appear first in the form.

4. Input Component as an example

You can keep adding elements and put that component in the switch statement in thedynamic-form.component.html by declaring the use in the dynamic-form.module.ts.

As shown, we are inheriting behaviours from the BaseFormDirective that we added before.

We are also inheriting form controls from the parent component using the code below. To understand more about nested template-driven form, go here.

viewProviders: [{ provide: ControlContainer, useExisting: NgForm }]

In the input template we are using the template-driven form and two-way binding with val that can be seen in the BaseFormDirective and provide properties of the field or metadata to the input form element.

5. Use it NOW

In app.component.html or any component where you want to render the form, add the following.

In app.component.html, as you see, we provide fields with metadata and data for two-way binding.

End result will be …

Conclusion

You can add more html elements and provide specific metadata for those elements. Fordropdown,you might want to provide options as a KeyValue Pair and for the text area, you might need a row property. You can also add more validations as well as your company’s theme just like the library you are using. You can also convert the component into the library and reuse it in multiple projects.

With dynamic components, we are controlling the behavior of the html elements by metadata reducing code duplication, creating a clean theme, increasing development velocity, and more and more.

--

--