1

我正在使用 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;
        }

    }

这个返回错误:无法读取 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 得到的结果是完美的。谁能帮助我我的错误是什么。提前致谢。

可以在这里看到一个 stackblitz 示例。

4

2 回答 2

1

我不确定这是否是一个原因,但是您并没有等待您的 api 调用的结果。你的代码总是返回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 is Mark,如果你写了禁止的名字,那么输入不会保存这个值:

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

可以在这里看到一个例子。

于 2020-02-26T12:11:08.520 回答
0

Angular Custom Validations 包含不同的范围,因此您制作的第一个示例不起作用。

由于您使用了“箭头函数”,第二个示例确实有效。因为您的自定义验证是异步的,所以您需要返回一个 observable。看看以下

第一个选项:

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(this) 是魔法发生的地方

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
                }
            )
        );
}
于 2020-02-26T12:11:23.950 回答