【问题标题】:custom validator in angular4 material table results errorangular4材料表结果错误中的自定义验证器
【发布时间】:2020-06-10 06:58:45
【问题描述】:

我正在使用 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 得到的结果是完美的。谁能帮助我我的错误是什么。 提前致谢。

A stackblitz example can be seen here.

【问题讨论】:

    标签: angular angular-material-table angular-custom-validators mat-form-field


    【解决方案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;
    }
    

    更新:

    您可以添加自定义验证器。禁止名是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;
      };
    }
    

    An example can be seen here.

    【讨论】:

    • 感谢分享。我试过异步等待一件事api函数没有返回值我们需要订阅还是管道,映射来获取数据
    • 并且由于值不返回 core.js:12584 错误错误:未捕获(承诺中):TypeError:无法读取未定义的属性“长度”类型错误:无法读取 MatTableValidatorService 未定义的属性“长度”。 (m
    • 我刚刚添加了 toPromise 现在它的工作仍然 formcontrol 为正确的输入返回错误
    • 我在 arrayval>0 中给了控制台,它返回 true,但仍然 formcontrol 在错误范围内
    • @KavyaShree 你能创建一个stackblitz 的例子吗?
    【解决方案2】:

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

    第二个示例确实有效,因为您使用了“箭头函数”。 因为您的自定义验证是异步的,所以您需要返回一个 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
                    }
                )
            );
    }
    

    【讨论】:

    • 感谢您的帮助。我仍然收到此错误 DnsDashboardComponent.html:29 错误类型错误:无法在推送时读取未定义的属性“api_call”../src/app/@core/matTable-validator.service.ts.MatTableValidatorService.nameValidator
    • 在声明字段时添加“绑定”函数,如下所示:new FormControl(null, [Validators.required, this.nameValidator.bind(this)])。这样您就可以明确地说自定义验证函数与组件具有相同的范围。我将编辑评论。
    • 我更新了代码,现在错误消失了,但是 api 没有返回地图内的值我试图控制台 api 命中但没有响应
    • 你能查一下吗?
    • 我更新了评论。看看 asyncValidators
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    • 1970-01-01
    • 2013-08-04
    • 2019-06-01
    • 2017-09-11
    • 1970-01-01
    相关资源
    最近更新 更多