HJ1990
HJ1990

Reputation: 415

Angular - Creating dynamic validation for forms

I am trying to create dynamic validation for forms. Since the forms are not static and are dynamically created, the names that I give for the formControlName comes from the ngFor. Everything seems to be working correctly and the only issue I am facing is with displaying the error message. Because the names come the {{e.Title}}, when I try to do editForm.controls.{{e.Title}}.errors?.required, it doesn't like the {{e.Title}} in there. In there a way to fix this ?

<mat-error *ngIf="editForm.controls.{{e.Title}}.errors?.required"></mat-error>

Example of what I am trying to do:

<mat-error *ngIf="editForm.controls.test?.errors?.toggle && !editable"></mat-error>

HTML

<form [formGroup]="editForm" (ngSubmit)="submitForm()" fxFill fxLayout="column" fxLayoutGap="5px">
    <ng-container *ngFor="let e of template; let i = index" [ngSwitch]="e.Type">
      <ng-template [ngSwitchCase]="0">
          <mat-form-field class="item-container" appearance="outline" floatLabel="always" fxFill>
            <mat-label class="title title-input-property">Employee Name</mat-label>
            <input #fn formControlName="{{e.Title}}" matInput placeholder="Please enter your name" required>
            <mat-error *ngIf="editForm.controls.{{e.Title}}.errors?.required"></mat-error>
          </mat-form-field>
      </ng-template>

    <ng-template [ngSwitchCase]="1">
          <mat-form-field class="item-container" appearance="outline" floatLabel="always" fxFill>
            <mat-label class="title title-input-property">Employee Number</mat-label>
            <input #fn formControlName="{{e.Title}}" matInput placeholder="Please enter your employee number" required>
            <mat-error *ngIf="editForm.controls.{{e.Title}}.errors?.required"></mat-error>
          </mat-form-field>
      </ng-template>
    </ng-container>
</form>

TS

ngOnInit(): void {
  this.editForm = this.formBuilder.group(this.ValidatorsTwo(this.elements);

}


 public ValidatorsTwo(elements: any[]) : any {
    const validateItems = [];
    elements.forEach((e, i) => {
      let a;
      switch (e.Type) {
      case 0: {
        if (e.Required) {
          a = { e.Title: ['', [this.requireValidator()]] };
        } else {
          a = { e.Title: [''] };
        }
        validateItems.push(a);
        break;
      } 
      // etc 
      default: {
        break;
      }
      }
    });
    const validationArray = Object.assign({}, ...validateItems);
    return validationArray;
}

Upvotes: 0

Views: 359

Answers (1)

Petr Averyanov
Petr Averyanov

Reputation: 9476

You use same syntax as in component:

<mat-error *ngIf="editForm.controls[e.Title].errors?.required"></mat-error>

or

<mat-error *ngIf="editForm.get(e.Title).hasError('required')"></mat-error>

Also I personally prefer [formControlName]="e.Title" to formControlName="{{e.Title}}" but this is up to you.

Upvotes: 1

Related Questions