0

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

8
  • why are you using document.getElementsByClassName in angular Commented Aug 8, 2018 at 7:05
  • Because I want to query elements of form with specified class only. Commented Aug 8, 2018 at 7:07
  • in angular you can select element using element ref Commented Aug 8, 2018 at 7:10
  • yes code can be optimized later but now it is needed to solve current problem. Commented Aug 8, 2018 at 7:13
  • do you want to create form with dynamic data? Commented Aug 8, 2018 at 7:15

1 Answer 1

3

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);
  }
}
Sign up to request clarification or add additional context in comments.

6 Comments

Hi thanks but how the elements in form will be binded to formGroup without formControlName?
They will have a form control name, you just have to iterate over it and use the name property
But with this solution I create names twice in html side and ts side. So it is like creating usual reactive form. Could you please provide sample? thanks
No you don't ... You simply use a loop in your HTML <input type="text" *ngFor="let control of controls" [formControlName]="control.name">.
but this will work only on same elements such as input. What if form is mix of inputs,selects ,checkboxes and so on with mixed order?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.