Как добавить динамические пользовательские проверки в angular2 (ReactiveForms)?

У меня есть требование, где я хочу реализовать логику для динамического назначения данных массива объектов для управления вводом и на основе обновления я хочу обновить свой массив, а также запустить проверку, чтобы проверить, имеют ли введенные имена / данные в элементе управления дублирующиеся записи. Для проверки я использовал модуль ReactiveForm. Но я сталкиваюсь ниже 2 вопросов -

  1. Как создать такую ​​же структуру массива, чтобы при успешной проверке я мог напрямую передать обновленную структуру в api?
  2. Как я назначаю идентификатор из объекта массива для formControlName, в настоящее время я назначаю его с индексом цикла.
    ссылка на плункар здесь - https://plnkr.co/edit/RSBpT0sFSI1GDCp6K7VR?p=preview

Составная часть:

@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>
  `
})

Класс (аннотация):

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)
        );
      }
    }

Любая помощь приветствуется!

1 ответ

Решение

Один из способов решить обе эти проблемы - подписаться на .valueChanges событие FormGroup и положить метод проверки, чтобы проверить значения FormControl для дублированного условия.

Также назначьте свойство custId при создании и добавлении FormControl в FormGroup в ngOnInit()

Фрагмент кода -

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 { }
Другие вопросы по тегам