angulartypescriptangular-formsformgroups

Create dynamic fields and apply validation in angular


I have this sample object

[
    {
        "labelName": "Name",
        "inputType": "textbox",
        "inputValues": "",
        "mandatory": "yes"
    },
    {
        "labelName": "Email",
        "inputType": "textbox",
        "inputValues": "",
        "mandatory": "yes"
    },
    {
        "labelName": "address 2",
        "inputType": "textarea",
        "inputValues": null,
        "mandatory": "yes"
    },
    {
        "labelName": "City",
        "inputType": "dropdown",
        "inputValues": null,
        "mandatory": "no"
    }
]

through which i need to generate form controls

ts:

FormGroup: FormGroup;
 this.fieldsData.forEach((ele, i) => {
 form[ele?.labelName]=new FormControl('',[Validators.required]);
 });
 this.FormGroup=new FormGroup(form);

HTML:

 <form [formGroup]="FormGroup">
        <div *ngFor="let data of fieldsData">
        <label>{{data.labelName}} </label>
        <input type="text" formControlName="{{data.labelName}}">
        </div>
        <button class="btn-submit" type="button" [disabled]="!FormGroup.valid" style="margin-top: 20px" (click)="SubmitDemo()">
            Submit
        </button>
 </form>

Here issue is i want to apply validation based on mandatory key if yes then apply validation, and if type is textbox then bind in input type='text' if dropdown bind in dropdown control.

Any solution Thanks


Solution

  • We can use ngSwitch in HTML to switch between input types.

    We can use a ternary condition, to assign the mandatory based on the condition.

    import { Component } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import {
      ReactiveFormsModule,
      FormControl,
      FormGroup,
      Validators,
    } from '@angular/forms';
    import 'zone.js';
    import { CommonModule } from '@angular/common';
    
    @Component({
      selector: 'app-root',
      standalone: true,
      imports: [CommonModule, ReactiveFormsModule],
      template: `
        <form [formGroup]="FormGroup">
                <div *ngFor="let data of fieldsData">
                <ng-container [ngSwitch]="data.inputType">
                  <ng-container *ngSwitchCase="'dropdown'">
                    <select name="cars" id="cars">
                      <option value="volvo">Volvo</option>
                      <option value="saab">Saab</option>
                      <option value="mercedes">Mercedes</option>
                      <option value="audi">Audi</option>
                    </select>
                  </ng-container>
                  <ng-container *ngSwitchCase="'textbox'"><textarea [formControlName]="data.labelName"></textarea></ng-container>
                  <ng-container *ngSwitchDefault><input type="text" [formControlName]="data.labelName"></ng-container>
                </ng-container>
                <label>{{data.labelName}} </label>
                
                </div>
                <button class="btn-submit" type="button" [disabled]="!FormGroup.valid" style="margin-top: 20px" (click)="SubmitDemo()">
                    Submit
                </button>
        </form>
      `,
    })
    export class App {
      fieldsData = [
        {
          labelName: 'Name',
          inputType: 'textbox',
          inputValues: '',
          mandatory: 'yes',
        },
        {
          labelName: 'Email',
          inputType: 'textbox',
          inputValues: '',
          mandatory: 'yes',
        },
        {
          labelName: 'address 2',
          inputType: 'textarea',
          inputValues: null,
          mandatory: 'yes',
        },
        {
          labelName: 'City',
          inputType: 'dropdown',
          inputValues: null,
          mandatory: 'no',
        },
      ];
      FormGroup!: FormGroup;
    
      ngOnInit() {
        const form: any = {};
        this.fieldsData.forEach((ele, i) => {
          const validators = ele?.mandatory === 'yes' ? [Validators.required] : [];
          form[ele?.labelName] = new FormControl('', validators);
        });
        this.FormGroup = new FormGroup(form);
      }
    
      SubmitDemo() {}
    }
    
    bootstrapApplication(App);
    

    Stackblitz Demo