0
votes

As you know when we create forms with Reactive Forms in Angular we assign formcontrolname to elements and also manually create formcontrols like below:

<form   [formGroup]="ntForm" (change)="onChange($event)" (ngSubmit)="onSubmit()" class="nt-form">
  <mat-form-field class="example-full-width">
    <input  matInput placeholder="User Id" formControlName="userId" [min]="5">
    <mat-error >{{getErrors('userId')}}</mat-error>
  </mat-form-field>

  <mat-form-field class="example-full-width">
    <input matInput placeholder="Id"  formControlName="id" required [min]="10">
    <mat-error >{{getErrors('id')}}</mat-error>
  </mat-form-field>

  <mat-form-field class="example-full-width">
    <input matInput placeholder="Title" formControlName="title" [email]="true">
    <mat-error >{{getErrors('title')}}</mat-error>
  </mat-form-field>

  <button class="nt-form-button" type="submit">Submit</button>

Manually adding formcontrols:

 this.ntForm = this.form.group({
      'id': new FormControl('id'),
      'userId': new FormControl('userId'),
      'title': new FormControl('title')   
    });

This may seems simple at first but what about if we have 20 elements? We need to manually add names and maintain them. In Agile development it will be pain. To solve this I create a function which auto create controls based on formControlName attribute:

 fillControls(data) {
    const els: any = document.getElementsByClassName('nt-form')[0]
      .querySelectorAll('[formControlName]');
    els.forEach(node => {
      const controlName = node.attributes['formcontrolname'].nodeValue;
      this.ntForm.addControl(controlName, new FormControl('', []));
    });
  }

But with this approach errors will be emitted stating ('Cannot find control with name: '') because I firstly initialize form with empty controls and them fill it. How can I solve this problem? thanks

1
why are you using document.getElementsByClassName in angularChellappan வ
Because I want to query elements of form with specified class only.Vugar Abdullayev
in angular you can select element using element refChellappan வ
yes code can be optimized later but now it is needed to solve current problem.Vugar Abdullayev
do you want to create form with dynamic data?Chellappan வ

1 Answers

3
votes

In my opinion, you're doing it wrong.

Instead of getting the control names from HTML, you should get it from the TS and iterate over it from the HTML.

For instance, you could use an interface to create form controls, use a static method to create a form group from it, and iterate over the interfaced elements in your HTML.

export interface ReactiveFormControl {
  name: string;
  placeholder: string;
  defaultValue: string;
  validators: Validators[];
}

export class ReactiveFormUtils {
  public static toFormGroup(builder: FormBuilder, controls: ReactiveFormControl[]) {
    const form = {};
    controls.forEach(control => form[control.name] = [control.defaultValue, [...control.validators]]);
    return builder.group(form);
  }

  public static getControlNames(controls: ReactiveFormControl[]) {
    return controls.map(control => control.name);
  }
}