Part 1: Create Configuration Based Dynamic Forms in Angular
Tags: angular, dynamicforms, forms, configuration
Published: 2023-08-06 09:55:20

---
title: Part 1: Create Configuration Based Dynamic Forms in Angular 
published: true
description: In this article, we explore the powerful world of dynamic forms in Angular using reactive forms. Learn how to create flexible and interactive forms based on a configuration file. Whether you're new to Angular forms or looking to enhance your skills, this article provides valuable insights into leveraging the full potential of Angular's reactive forms. Dive in and discover the true power of dynamic forms! 🚀
tags: Angular, DynamicForms, Forms, Configuration
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qyb5fn514p0vnveann6o.png
# Use a ratio of 100:42 for best results.
# published_at: 2023-08-06 07:23 +0000
---
## Introduction 

Hey there, fellow developers! Welcome to the first part of our series on creating **dynamic forms** in Angular based on configuration files. In this article, I'll guide you through the process of building a **flexible** and **interactive** form using Angular's reactive forms approach. We'll leverage a **configuration model** to control form fields, validators, and error messages dynamically. By the end of this article, you'll be able to:

* Create dynamic form fields based on the configuration provided.
* Control the form fields by adjusting the model interface to suit your needs.
* Display separate error messages for each validation case.
* Pass separate validators for each field in the configuration.

## Code Example

Find a live code example on StackBlitz [here](https://stackblitz.com/edit/stackblitz-starters-lx22ym?file=src%2Fmain.ts). Feel free to explore the code and experiment with dynamic forms yourself!

Let's dive in! 🚀

## Understanding the Goal

_Our main objective is to develop a robust form component capable of generating dynamic form fields based on a configuration file_. The cornerstone of this system is the `DynamicFormFieldModel`, enabling us to define essential properties for each form field:

- `id`: A unique key serving to identify the dynamic form field.
- `label`: Presented as a placeholder or title for the field.
- `type`: Determines the type of form field component to be rendered, such as a text input or a dropdown/select.
- `selectMenuOptions` (optional): Defines an array of options for the dropdown if the field is of type 'select'.
- `value` (optional): Provides a default value for the form field, with an empty string used as the default if unspecified.
- `validators` (optional): Empowers us to apply specific validation rules to the field using an array of Angular Validators.

With the versatile `DynamicFormFieldModel`, we can easily customize and extend our form fields based on the configuration, making it a potent solution for creating dynamic forms with diverse input types and validation requirements.

Feel free to add as many fields as needed; the system accommodates future scenarios, such as incorporating new components (e.g calendar). There is no limit to the fields we can add, providing flexibility and adaptability to our form-building capabilities.

Now, let's delve into the implementation details! 💻

```typescript
export interface DynamicFormFieldModel {
  id: string;
  label: string;
  type: DynamicFormFieldModelType;
  selectMenuOptions?: SelectMenuOption[];
  value?: string | SelectMenuOption[];
  validators?: ValidatorFn[];
}
```

## Building the Dynamic Form Field Component

In this section, we will explore the `dynamic-form-field.component.ts` file, which serves as the cornerstone of our dynamic form fields implementation. By leveraging Angular's powerful `FormGroupDirective`, we gain access to the root form of the parent component that hosts our dynamic form fields. This connection allows us to seamlessly render different types of form fields based on the `type` property derived from the `DynamicFormFieldModel` provided in the configuration.

```typescript
...
export class DynamicFormFieldComponent {
  @Input() formItem!: DynamicFormFieldModel;
  form!: FormGroup;

  constructor(private rootFormGroup: FormGroupDirective) {
   this.form = this.rootFormGroup.control;
  }
}
```

## Defining the Model

The `dynamic-form-field.model.ts` file houses our configuration model. Here, we define the types and interfaces for our dynamic form fields. The `DynamicFormFieldModelType` allows us to restrict the available field types to `'text'` or `'select'`.

It is important to note that if we plan to add more input elements to the dynamic-form-field.component, we must proactively update the DynamicFormFieldModelType as well. This proactive approach ensures that the model remains accurate and reflects the latest available field types, enabling seamless integration of new input elements without any compatibility issues. By maintaining consistency between the component and the model, we guarantee smooth expansion and optimization of our dynamic form-building capabilities.

```typescript
export type DynamicFormFieldModelType = 'text' | 'select';

export interface SelectMenuOption {
  label: string;
  value: string;
}

export interface DynamicFormFieldModel {
  id: string;
  label: string;
  type: DynamicFormFieldModelType;
  selectMenuOptions?: SelectMenuOption[];
  value?: string | SelectMenuOption[];
  validators?: ValidatorFn[];
}
```

## Rendering the Dynamic Form Fields

In `dynamic-form-field.component.html`, we leverage Angular's `ngSwitch` to dynamically render the appropriate form field based on its type. We efficiently control the dynamic generation of form fields while ensuring separate error messages for each validation case. The `form` property, represented by a `FormGroup`, is initialized with the root form control of the parent component. This design enables smooth synchronization of values and validation between the parent form and the `DynamicFormFieldComponent`.

```html
<div class="dynamic-form-field-container">
  <ng-container [formGroup]="form">
    <ng-container [ngSwitch]="formItem.type">
      <mat-form-field *ngSwitchCase="'text'">
        <!-- ... -->
      </mat-form-field>
      <mat-form-field *ngSwitchCase="'select'">
        <!-- ... -->
      </mat-form-field>
    </ng-container>
  </ng-container>
</div>
```

## Assembling the Main Application Component

In this approach, we leverage the setupFormFields function to dynamically generate form fields based on the configuration specified in the `dynamicFormFields` variable.

By calling this function, we iterate through each item in the configuration and create the corresponding form control using Angular's `FormBuilder` service. This allows us to define the initial value for each form field, which is derived from the `value` property in the configuration. If no default value is provided, we simply set an empty string as the default.

Additionally, we have the flexibility to apply custom validation rules to each field by utilizing the `validators` property in the configuration. This ensures that the form fields adhere to specific requirements and constraints, providing a reliable and interactive user experience.

The true beauty of this approach lies in its adaptability. By making changes to the configuration, such as adding new fields or altering their order, the form dynamically adjusts to reflect these modifications. As a result, we have a highly flexible and efficient way to create complex and interactive forms that can cater to various scenarios.


```typescript
//...
export class App {
  myForm!: FormGroup;
  dynamicFormFields: DynamicFormFieldModel[] = [
    // ...
  ];

  constructor(private fb: FormBuilder) {
    this.myForm = this.fb.group({});
    this.setupFormFields();
  }

  setupFormFields() {
    this.dynamicFormFields.forEach((formItem: DynamicFormFieldModel) => {
      let formControl;
      formControl = this.fb.control(formItem.value || '', formItem.validators);
      this.myForm.addControl(formItem.id, formControl);
    });
  }}
```

## Displaying the Dynamic Form in the App Component

Finally, in `app.component.html`, we render the dynamic form fields by iterating through the `dynamicFormFields` array. Each form field is displayed using the `dynamic-form-field` component.

```html
<ng-container [formGroup]="myForm">
  <!-- Generator -->
  <ng-container *ngFor="let formItem of dynamicFormFields">
    <dynamic-form-field [formItem]="formItem"></dynamic-form-field>
  </ng-container>
</ng-container>
<section>
  <button mat-raised-button color="primary" [disabled]="!myForm.valid">
    Click me
  </button>
</section>
```

## Conclusion

Congratulations! In this article, we've successfully created dynamic and interactive forms in Angular by utilizing a **configuration-driven** approach. By leveraging the `DynamicFormFieldModel`, customizing form properties, and using `ngSwitch`, we've built a powerful form component that can handle various form fields with ease.

**Stay tuned** for the next article, where we'll dive deeper into the magic of dynamic forms. We'll explore how to break down each form field into separate components, further enhancing the reusability and maintainability of our dynamic forms. Until then, happy coding! 🚀