简体   繁体   中英

How to add dynamic custom validations in angular2 (ReactiveForms)?

I have requirement where I want to implement logic to assign object array data to input control dynamically and based on updation I want to update my array as well as I want to fire validation to check whether entered names/data in control having duplicate entries. For validation I have used ReactiveForm module. But I am facing below 2 issues –

  1. How I create the same array structure so that on successful validation I can directly pass the updated structure to api?
  2. How I assign id from array object to formControlName, currently I am assigning it with loop index.
    plunkar reference here - https://plnkr.co/edit/RSBpT0sFSI1GDCp6K7VR?p=preview

Component:

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h3> Custom Group Validation</h3>
      <form [formGroup]="myForm">
          <div class="left">
              names: <br>
              <div formArrayName="names">
                  <div *ngFor="let item of namesArray.controls; let i = index">
                      <input type="text" [formControlName]="i">
                      <button (click)="removeAt(i)">X</button><br>
                  </div>
              </div>

              <div *ngIf="namesArray.hasError('duplicate')">
                  duplicate entries
              </div>
              <pre>Array value: <br>{{namesArray.value | json}}</pre>
          </div>
      </form>
</div>
  `
})

Class (abstract):

namesArray:FormArray =  new FormArray([], this.customGroupValidation  );
    dataArray: { custId: number, customerName: string }[] = [
{ custId: 101, customerName: 'John' },
{ custId: 102, customerName: 'Mike' },
{ custId: 103, customerName: 'Julia' }];

    ngOnInit():void{
      for(let ele of this.dataArray){
          this.namesArray.push(
            new FormControl(ele.customerName)
        );
      }
    }

Any Help Appreciated!

One way to handle this both issues is subscribe to .valueChanges event of FormGroup and put the check in method to validate FormControl values for duplicate condition.

Also assign custId property while creating and adding FormControl to FormGroup in ngOnInit()

Code Snippet -

import { Component, NgModule, OnInit } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormBuilder, FormGroup, FormArray, AbstractControl, Validators, FormControl, ReactiveFormsModule } from '@angular/forms'

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h3> Custom Group Validation</h3>
      <form [formGroup]="customerFormGroup">
          <div class="left">
              names: <br>
              <div>
                  <div *ngFor="let item of dataArray">
                      <input type="text" [formControlName]="item.custId" [(ngModel)]="item.customerName">
                      <div *ngIf="customerFormGroup.controls[item.custId] && customerFormGroup.controls[item.custId].errors">
                        duplicate                       
                      </div>
                  </div>
              </div>
              <pre>Array value: <br>{{dataArray | json}}</pre>
          </div>
      </form>
</div>
  `
})
export class App implements OnInit {
  customerFormGroup: FormGroup = new FormGroup({});
  dataArray: { custId: number, customerName: string }[] = [
    { custId: 101, customerName: 'John' },
    { custId: 102, customerName: 'Mike' },
    { custId: 103, customerName: 'Julia' }];

  ngOnInit(): void {

    for (let ele of this.dataArray) {
      let control: FromControl = new FormControl(ele.customerName);
      this.customerFormGroup.addControl(ele.custId, control);
    }

    this.customerFormGroup.valueChanges.subscribe(
      data => this.onValueChanged(data)
    );
  }

  onValueChanged(data?: any) {
    if (!this.customerFormGroup) return;
    let formGroup = this.customerFormGroup;
    var result = _.groupBy(formGroup.controls, c => {
      if (c.value) return c.value.toLowerCase();
      else c.value;
    });
    for (let prop in result) {
      if (result[prop].length > 1) {
        _.forEach(result[prop], function (item: any) {
          if (item.dirty && item.value) {
            item.setErrors({
              'duplicate': true
            });
          }
        })
      }
    }
  }
}

@NgModule({
  imports: [BrowserModule, ReactiveFormsModule],
  declarations: [App],
  bootstrap: [App]
})
export class AppModule { }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM