如何从字符串获取验证器函数

时间:2018-10-09 20:12:06

标签: angular typescript angular5

如何将以下字符串数组转换为类型的数组(或函数?或这些验证器都...)

let valStrings: string[] = ["Validators.required", "Validators.maxLength(10)"];

并将其转换为:

let validators: ValidatorFn[] = [ Validators.required, Validators.maxLength(10) ];

我有一个返回验证规则的Web服务。这是尝试集中所有验证规则,以使服务器和客户端验证保持同步,因此字符串来自带有JSON结果的HttpClient调用。  当然,我们仍然将实际的实现分开,但是至少在两者之间定义的规则应该是相同的。

此验证器数组将被传递到FormControl中,以利用Angular中的反应形式进行客户端验证。

这是应该使用eval()的地方吗?

谢谢-亚当

3 个答案:

答案 0 :(得分:2)

通过字符串中的angular代码在服务器上定义验证是非常糟糕的主意。如果要进行动态验证,请为此创建一个API。喜欢:

heroku pg:copy DATABASE_URL HEROKU_POSTGRESQL_ROSE_URL --app my_app_name --confirm my_app_name

Eval不会帮助您,因为该类未捆绑在代码中。此外,eval还会带来安全风险,因此应该由CSP在您的站点上禁用它。

不将字符串转换为代码。您将需要一个解析器。当他们在Angular中更改验证时,您会怎么做?您会更新所有表格吗?

或者想象您将通过iOS应用程序连接到您的API。必须解析这些字符串Angular验证规则。

答案 1 :(得分:1)

我知道的唯一方法是使用if

let valStrings: string[] = ["Validators.required", "Validators.maxLength(10)"];
let validators=valString.map(x=>{
    switch (x)
    {
        if (x=="Validators.required")
            return Validators.required;
        if (x.startsWith("Validators.maxLength")
        {
            let length=+(x.split('(')[1].split(')')[0]);
            return Validators.maxLength(length)
        }
    }
});

答案 2 :(得分:0)

您可以在抽象服务中创建验证映射,并在需要时重用。


export const schema = {
    "defaultValidations": {
        'title': [
            { name: 'required' },
            { name: 'minLength', args: [3] }
        ],
        'firstName': [
            { name: 'required' },
            { name: 'minLength', args: [3] },
            { name: 'maxLength', args: [50] }
        ]
    }
}

export interface Dictionary<T> {
    [Key: string]: T;
}

  validationMap: Dictionary<any> = {
    "required": (arg: any[]) => Validators.required,
    "minLength": (arg: number[]) => Validators.minLength(arg[0]),
    "maxLength": (arg: number[]) => Validators.maxLength(arg[0])
  };

  constructor(private fb: FormBuilder) { }

  // validation functions
  mapValiations(key: string) :ValidatorFn[] {
    const validations = schema.defaultValidations[key]?.map(element => {
        return this.validationMap[element.name](element?.args);
     });

     return validations;
  }