angular4 material table 中的自定义验证器结果错误

custom validator in angular4 material table results error

我正在使用 angular4-material-table 。在那里我尝试添加自定义输入验证 我在那里创建了单独的验证器服务我调用了自定义函数来根据 api 结果命中我的 api 它会抛出输入有效与否。

这是我的代码,谁能告诉我我犯了什么错误,

import { Injectable } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { ValidatorService } from 'angular4-material-table';
import { AbstractControl } from '@angular/forms';
import { ApiCallService } from 'api.service';

    @Injectable()
    export class MatTableValidatorService implements ValidatorService {
        constructor( private api_call: ApiCallService) {  
        }
       getRowValidator(): FormGroup {
        return new FormGroup({
          'name': new FormControl(null, [Validators.required, this.nameValidator]),
          });
      }
        nameValidator(control: AbstractControl): { [key: string]: boolean } | null {
            this.api_call
            .api_function(parameter)
            .subscribe(data => {
              const arrayVal = data.response;
              if(arrayVal.length > 0)
              {
                return {'dnsCheck': true}
              }
              return null;
          });
            return null;
        }

    }

这个 returns 错误:无法读取 api_call 的 属性,即使我在构造函数

中声明了它

另一种方式:

   public nameValidator = (control: AbstractControl) => {
         this.api_call
            .api_function(parameter)
            .subscribe(data => {
              const arrayVal = data.response;
              if(arrayVal.length > 0)
              {
                return {'dnsCheck': true}
              }
              return null;
          });
        };

这种方式有效,但无论输入是否有效,它总是会抛出错误。我已经用控制台检查了输出,似乎从 api 得到的输出已经完美完成。任何人都可以帮助我我的错误是什么。 提前致谢。

A stackblitz example can be seen here.

我不确定这是否是一个原因,但是您并不是在等待 api 电话的结果。你的代码总是 return null。所以我们需要等待 API 调用的结果:

async nameValidator(control: AbstractControl): { [key: string]: boolean } | null {  
    const result = await this.api_call.api_function(parameter);
    const arrayVal = result.response;

    if (arrayVal.length > 0)
          return {'dnsCheck': true}

    return null;
}

更新:

您可以添加自定义验证器。 Forbidden name是Mark,如果你写forbidden name,那么input不会保存这个值:

@Injectable()
export class PersonValidatorService implements ValidatorService {
  getRowValidator(): FormGroup {
    return new FormGroup({
      'name': new FormControl(null, [Validators.required, forbiddenNameValidator()])

      });
  }
}

export function forbiddenNameValidator(): ValidatorFn {
  return (control: AbstractControl): {[key: string]: any} | null => {    
    const forbidden =  'Mark';
    console.log(`forbidden name is `, forbidden);
    return (forbidden == control.value) ? {'forbiddenName': {value: control.value}} : null;
  };
}

An example can be seen here.

Angular 自定义验证包含不同的范围,因此您制作的第一个示例不起作用。

自从您使用 'arrow function' 后,第二个示例确实有效。 因为您的自定义验证是异步的,所以您需要 return 一个可观察的。 看看下面

第一个选项:

nameValidator = (control: AbstractControl): Observable<{ [key: string]: boolean } | null> => {
    return this.api_call
        .api_function(parameter)
        .pipe(
            map(
                data => {
                    const arrayVal = data.response;
                    return arrayVal && arrayVal.length > 0 ? { 'dnsCheck': true } : null
                }
            )
        );
}

第二个选项:

this.nameValidator.bind(这)是奇迹发生的地方

getRowValidator(): FormGroup {
    return new FormGroup({
        'name': new FormControl(null, {
            asyncValidators: [this.nameValidator.bind(this)],
            validators: [Validators.required],
        }),
    });
}

nameValidator(control: AbstractControl): Observable < { [key: string]: boolean } | null > {
    return this.api_call
        .api_function(parameter)
        .pipe(
            map(
                data => {
                    const arrayVal = data.response;
                    return arrayVal && arrayVal.length > 0 ? { 'dnsCheck': true } : null
                }
            )
        );
}