如何在自定义验证器中获取组件变量?

时间:2019-07-08 11:07:27

标签: angular forms validation

我想使自定义验证器仅在表单中的文本唯一时才使提交按钮可用。 我有VulnarabilitiesClass实例,其中包含具有id和name字段的对象数组。 在表单中输入任何文本后,出现此错误: 错误:未定义不是对象(正在评估“ this.systemVulnarabilities”)

<form [formGroup]="profileForm">
  <label>
    Vulnarability Name:
    <input type="text" formControlName="name" required>
  </label>
</form>

<p>
  Form Status: {{ profileForm.status }}
</p>
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
<button type="submit" [disabled]="!profileForm.valid">Submit</button>
this.systemVulnarabilities = new VulnarabilitiesClass();

profileForm = this.fb.group({
    name: ['', Validators.required,this.UniqueNameValidator],
  });

private UniqueNameValidator(control: FormControl): ValidationErrors{
  let vulnarabilityName: string = control.value;
  console.log(vulnarabilityName);
  console.log(this.systemVulnarabilities.displayList.toString());//no output already
  let found: number = this.systemVulnarabilities.displayList.map(function(e) { return e.name; }).indexOf(vulnarabilityName); //mistake
  if(found === -1){
    return {invalidPassword: 'this name already exists'};
  }
  return null;
}

3 个答案:

答案 0 :(得分:2)

发生此错误是因为执行UniqueNameValidator方法与组件上下文this不同。原因是在javascript上下文this中取决于函数的执行方式,而不是函数的声明位置。

简单的解决方法是使用Function.prototype.bind方法来确保正确的上下文this

this.UniqueNameValidator.bind(this)

此外,如果验证器是同步的,则需要将验证器包装在数组中,否则Angular会将其视为异步验证器:

name: ['', [Validators.required, this.UniqueNameValidator.bind(this)]],

答案 1 :(得分:1)

另一种“经典”方式是定义函数,如

private UniqueNameValidator(){
  return (control: FormControl)=>{
         ....
  }
}

并添加验证器-请参见UniqueNameValidator末尾的()

profileForm = this.fb.group({
    name: ['', Validators.required,this.UniqueNameValidator()],
  });

答案 2 :(得分:0)

我认为您可以使用闭包,并使用变量systemVulnarabilities使Validator上下文相关,如下所示:


profileForm = this.fb.group({
    name: ['', Validators.required,this.UniqueNameValidator(systemVulnarabilities)],
  });

UniqueNameValidator(systemVulnarabilities): ValidatorFn {
  return (control: FormControl)=>{
    let vulnarabilityName: string = control.value;
  let found: number = systemVulnarabilities.displayList.map(function(e) { return e.name; }).indexOf(vulnarabilityName); //mistake
  if(found === -1){
    return {invalidPassword: 'this name already exists'};
  }
  return null;
  }
}