angulartypescriptangular-reactive-formsangular-forms

How to disable dynamic control in angular


I'm trying to create dynamic fields using this code

formInputfieldsForm: FormGroup[];

    defaultFields: any = [
        { inputType: 'textbox', inputValues: '' },
        { inputType: 'textbox', inputValues: '' },
      ]
    
     createForm(a?: any, b?: any, c?: any): FormGroup {
        return this.formService.group({
          "inputType": [b, Validators.required],
          "inputValues": [c, Validators.required],
        })
      }
    
     addFields(){
        this.defaultFields.forEach((ele, i) => {
          this.formInputfieldsForm.push(this.createForm(ele?.inputType, ele?.inputValues));
        });
      }

    createFieldsForm(): FormGroup {
    return this.formService.group({
      "inputType": [null, Validators.required],
      "inputValues": [null, Validators.required],
    })
  }

 
  addFields(){
    this.formInputfieldsForm.push(this.createFieldsForm());
  }

every time addFields is called new dynamic fields are created

in frontend i'm using loop to render elements like this

<div *ngFor="let expForm of formInputfieldsForm; let i = index;" [formGroup]="expForm">
 
<select class="hand_symbol" formControlName="inputType"  placeholder="Select Input Type">
                                                <option value="">Select</option>
                                                <option value="textbox">Textbox</option>
                                                <option value="dropdown">Drop Down</option>
                                                <option value="textarea">Textarea</option>
                                              </select>

<input class="form-control" formControlName="inputValues" type="text" placeholder="Enter Values" type="text">
</div>



<span title="Add" (click)="addFields()">add</span>

it is rendered now i need by default inputValues control should be disabled and if i select dropdown from select control then only it should be enabled

any solution Thanks


Solution

  • We can use (change) event to get the form group and validate if it should be enabled or disabled.

      dropdownChanged(index: number) {
        const formGroup = this.formInputfieldsForm.at(index);
        const values = formGroup.value;
        formGroup.get('inputValues')!.setValue(null);
        if (values.inputType === 'dropdown') {
          formGroup.get('inputValues')!.enable();
        } else {
          formGroup.get('inputValues')!.disable();
        }
      }
    

    We can use a ternary condition check if the default value is dropdown and if we should enable/disable it.

      createForm(b?: any, c?: any): FormGroup {
        return this.fb.group({
          inputType: [b, Validators.required],
          inputValues: [
            b === 'dropdown' ? c : { value: c, disabled: true },
            Validators.required,
          ],
        });
      }
    

    Full Code:

    import { CommonModule } from '@angular/common';
    import { Component, inject } from '@angular/core';
    import {
      FormArray,
      FormBuilder,
      FormGroup,
      ReactiveFormsModule,
      Validators,
    } from '@angular/forms';
    import { bootstrapApplication } from '@angular/platform-browser';
    import 'zone.js';
    
    @Component({
      selector: 'app-root',
      imports: [CommonModule, ReactiveFormsModule],
      standalone: true,
      template: `
        <div *ngFor="let expForm of getFields(); let i = index;" [formGroup]="expForm">
            <select class="hand_symbol" formControlName="inputType"  placeholder="Select Input Type" (change)="dropdownChanged(i)">
              <option value="">Select</option>
              <option value="textbox">Textbox</option>
              <option value="dropdown">Drop Down</option>
              <option value="textarea">Textarea</option>
            </select>
            <input class="form-control" formControlName="inputValues" type="text" placeholder="Enter Values" type="text">
        </div>
     
     
     
     <span title="Add" (click)="addFields()">add</span>
      `,
    })
    export class App {
      formInputfieldsForm: FormArray<any> = new FormArray<any>([]);
      fb = inject(FormBuilder);
      defaultFields: any = [
        { inputType: 'textbox', inputValues: '' },
        { inputType: 'textbox', inputValues: '' },
      ];
    
      getFields() {
        return this.formInputfieldsForm.controls as FormGroup[];
      }
    
      dropdownChanged(index: number) {
        const formGroup = this.formInputfieldsForm.at(index);
        const values = formGroup.value;
        formGroup.get('inputValues')!.setValue(null);
        if (values.inputType === 'dropdown') {
          formGroup.get('inputValues')!.enable();
        } else {
          formGroup.get('inputValues')!.disable();
        }
      }
    
      createForm(b?: any, c?: any): FormGroup {
        return this.fb.group({
          inputType: [b, Validators.required],
          inputValues: [
            b === 'dropdown' ? c : { value: c, disabled: true },
            Validators.required,
          ],
        });
      }
    
      ngOnInit() {
        this.addFieldsOnLoad();
      }
    
      addFieldsOnLoad() {
        this.defaultFields.forEach((ele: any, i: any) => {
          this.formInputfieldsForm.push(
            this.createForm(ele?.inputType, ele?.inputValues)
          );
        });
      }
    
      createFieldsForm(): FormGroup {
        return this.fb.group({
          inputType: [null, Validators.required],
          inputValues: [null, Validators.required],
        });
      }
    
      addFields() {
        this.formInputfieldsForm.push(this.createForm('', ''));
      }
    }
    
    bootstrapApplication(App);
    

    Stackblitz Demo