代码之家  ›  专栏  ›  技术社区  ›  JSON

如何将参数传递给异步验证器以进行被动角度控制?

  •  6
  • JSON  · 技术社区  · 7 年前

    问题

    我对读取/编辑例程使用相同的组件。 async-validator 与新条目完美配合。如果用户意外更改了值并试图恢复到保存的值,则会出现问题。我的当前代码将运行,并返回现有值。我想传递更多数据和控制值,以便验证该对值是否已经存在。

    我正在发布相关代码,

    这是我的 form control ,则,

    patientEmail: new FormControl(
        null,
        [Validators.email, Validators.required],
        FormControlValidator.createEmailAsyncValidator(
          this.asyncValidatorService
        ),
      ),
    

    我的异步验证器创建者类是,

    export class FormControlValidator {
      static createEmailAsyncValidator(asyncValidatorService: AsyncValidationService) {
        return (control: AbstractControl) => {
          if (!control.pristine) {
            control.markAsPristine();
            return asyncValidatorService
              .validateEmailNotTaken(control)
              .map((response: HttpResponse<boolean>) => {
                return !response.body ? null : { taken: true };
              });
          }
          return Observable.of(null);
        };
      }
    

    最后是我的服务,

    @Injectable()
    export class AsyncValidationService {
      constructor(private httpService: HttpClientService) {}
    
      public validateEmailNotTaken(control: AbstractControl) {
        return this.httpService.getRequest(
          'PatientsRegistration/IsPatientEmailExist?email=' + control.value,
        );
      }
    }
    

    我想把另一个参数传给我的 createEmailAsyncValidator ,如果可能,类似于表单中的另一个控件值。

    2 回复  |  直到 4 年前
        1
  •  1
  •   Tomasz Kula    7 年前

    如果需要基于另一个控件验证控件,则需要将验证器提升到父控件。下面是一个验证器示例,它检查电子邮件是否以人名(另一个控制值)开头。

    应用程序。组成部分ts

    import { Component } from '@angular/core';
    import {FormBuilder, FormControl, FormGroup, ValidatorFn} from '@angular/forms'
    
    const personalEmailValidator: ValidatorFn = (ctrl: FormGroup) => {
      const email = ctrl.get('email') as FormControl;
      const name = ctrl.get('name') as FormControl;
    
      const valid = (email.value || '').startsWith(name.value);
    
      return valid ? null : { personalEmailError: 'Email must start with a person name'}
    }
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  {
    
      form: FormGroup;
    
      constructor(private fb: FormBuilder) {
        this.form = this.fb.group({
          email: [null],
          name: [null]
        }, { validator: personalEmailValidator })
      }
    }
    

    应用程序。组成部分html

    <input [formControl]="form.get('name')" placeholder="name" />
    <input [formControl]="form.get('email')" placeholder="email" />
    
    {{ form.hasError('personalEmailError') ? form.getError('personalEmailError') : 'form is valid'}}
    

    Live demo

        2
  •  0
  •   JSON    7 年前

    所以我以另一种方式工作,灵感来自 Tomasz Kula answer

    我创建了一个异步 Directive 实现 AsyncValidator 界面 我将额外的参数作为“对象”传递,在我的情况下,它看起来是这样的,

    {
     coupledControl: AbstractControl,
     method: {
              apiUrl: string
             }
    } 
    

    这是我的 directive 密码

    import { Directive, forwardRef, Input } from '@angular/core';
    import { NG_ASYNC_VALIDATORS, Validator, AbstractControl } from '@angular/forms';
    import { Observable } from 'rxjs/Observable';
    import { HttpClientService } from '../../../../../shared/services/httpclient.service';
    import { HttpResponse } from '@angular/common/http';
    import { IAsyncMethod } from './../interfaces/async-methods-interface';
    
    
    @Directive({
      // tslint:disable-next-line:directive-selector
      selector: '[asyncValidator][formControlName], [asyncValidator][ngModel]',
      providers: [
        {
          provide: NG_ASYNC_VALIDATORS,
          useExisting: forwardRef(() => AsynValidatorDirective),
          multi: true,
        },
      ],
    })
    export class AsynValidatorDirective implements Validator {
      @Input() asyncValidator: { coupledControl: AbstractControl; method: IAsyncMethod };
    
      validate(
        control: AbstractControl,
      ): Promise<{ [key: string]: any }> | Observable<{ [key: string]: any }> {
        return this.validateIsExistAsync(control);
      }
    
      constructor(private httpService: HttpClientService) {}
      validateIsExistAsync(control: AbstractControl) {
        if (!control.pristine) {
          const coupledControl: AbstractControl = this.asyncValidator.coupledControl;
          const method: IAsyncMethod = this.asyncValidator.method;
          return this.httpService
            .getRequest(method.apiUrl + '?control=' + control.value + '&id=' + coupledControl.value)
            .map((response: HttpResponse<boolean>) => {
              return !response.body ? null : { asyncInvalid: true };
            });
        }
        return Observable.of(null);
      }
    }
    

    在我的 HTML ,则,

     <input [asyncValidator]="{coupledControl: patientRestrationForm.get('patientFileId'), method: this.asyncMethods.validatePatientEmail }" [errorStateMatcher]="matcher" matInput autocomplete="off" formControlName="patientEmail">
    

    在我的后端,我检查存在和匹配,简单的逻辑!

    如果您有任何意见,

    推荐文章