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.
- 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 imports
whatever 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.