通过点击按钮的反应式表单进行异步验证。

问题描述 投票:0回答:1

我正在尝试验证数据库中是否存在一个名字。如果存在,我想把它标记为无效,并通知用户这个情况。

除此以外,我正在寻找最好的方法来完成这个任务:模板驱动的表单或反应式表单。

请注意,我使用的是多个表单,就像下面的例子一样。https:/material.angular.io。.

这是我目前的代码。

HTML:

<mat-horizontal-stepper [@.disabled]="true" #stepper>
  <mat-step label="Example" [stepControl]="nameForm">
    <form [formGroup]="nameForm">
      <mat-form-field>
        <mat-label>NAME</mat-label>
        <input matInput placeholder="Input name" formControlName="name">
      </mat-form-field>
      <button
        matTooltip="Verify name in data base"
        (click)="validateName()" <<<< LOOK, HERE IS THE POINT
        [disabled]="!loading">Validate Name
        <i class="ml-2 fa fa-refresh fa-spin" *ngIf="!loading"></i>
      </button>

      <div>
        <button mat-button matStepperNext>Next</button>
      </div>
    </form>
  </mat-step>

  <mat-step label="Endereço" [stepControl]="enderecoForm">
    <form [formGroup]="nameForm2">
      <mat-form-field>
        ...
      </mat-form-field>
    </form>
  </mat-step>

... more steps with one form inside of each one

TS:

export class SomeComponent {
  constructor(private readonly _formBuilder: FormBuilder) {}

  ngOnInit(): void {
    this.nameForm = this._formBuilder.group(
      {
        name: ['', Validators.required],
      },
      { validator: this.validateName },
    ); // AND HERE LOOK
    this.nameForm2 = this._formBuilder.group({
      name2: ['', Validators.required],
      // ... more forms and controls validators with reactive forms
    });
  }

  validateName(fb: FormGroup) {
    const nameCtrl = fb.get('name');
    // method verifyName return the name from database if exists
    const name = this.nameService.verifyName(nameCtrl);

    if (nameCtrl.errors == null || 'exists' in nameCtrl.errors) {
      if (name == null) {
        nameCtrl.setErrors(null);
      } else {
        nameCtrl.setErrors({ exists: true });
      }
    }
  }
}
angular typescript angular-material2 reactive-forms
1个回答
3
投票

我不太明白,如果你想用以下方法来验证 AsyncValidator 或点击按钮后,但我们在这里。

1. 要通过 asyncValidators:

import { Component } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';

import { Observable, of as just } from 'rxjs';
import { catchError } from 'rxjs/operators';

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'app-some',
  templateUrl: './some-component.html'
})
export class SomeComponent {
  readonly formGroup = this.formBuilder.group(
    {
      name: ['', Validators.required, this.validateName]
    },
    { updateOn: 'blur' }
  );

  constructor(private readonly formBuilder: FormBuilder) {}

  // For this case, I'd suggest you to name it something like `nameAsyncValidator`.
  // In any case it's up to you :)
  private validateName(): Observable<{ exists: boolean } | null> {
    const { errors, value } = this.formGroup.get('name')!;

    if (errors || !value) return just(null);

    return this.nameService.verifyName(value).pipe(
      catchError(() => just(null))
    );
  }
}
  • 请注意,我指定了 this.validateName 作为第3个参数,哪一个是特定的?asyncValidators.
  • 还请注意,我使用了 { updateOn: 'blur' } 以防止向服务器发出不必要的请求。这些请求将只在模糊时发出。
  • DEMO (完整版,包括加载处理和模拟版)

2. 要通过按钮点击验证。

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';

import { catchError, take, tap } from 'rxjs/operators';

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'app-some',
  templateUrl: './some-component.html'
})
export class SomeComponent {
  readonly formGroup = this.formBuilder.group({
    name: ['', Validators.required]
  });

  validateName(): void {
    const nameFormControl = this.formGroup.get('name')!;
    const { errors, value } = nameFormControl;

    if (errors || !value) return;

    return this.nameService.verifyName(value).pipe(
      take(1),
      catchError(() => just(null)),
      tap(exists => nameFormControl.setErrors(exists))
    )
    .subscribe();
  }
}

请注意,由于你没有包括签名的。nameServive.verifyName 在问题中,我假设它返回 Observable<{ exists: boolean } | null>.

© www.soinside.com 2019 - 2024. All rights reserved.