简体   繁体   English

如何在表单上实现自定义验证器,其中验证逻辑需要来自 observable 的数据

[英]How to implement custom validator on a form, where the validation logic requires data from an observable

I am trying to implement a custom validator on a form, which will check the form input and compare it to an array of values, to ensure the input value is unique.我正在尝试在表单上实现一个自定义验证器,它将检查表单输入并将其与值数组进行比较,以确保输入值是唯一的。 The array for comparison comes from an Observable.用于比较的数组来自 Observable。 However the array is appearing as undefined when I try to access it from the validation method, I'm assuming because I'm doing it in the wrong order in relation to the subscribe, however I cannot work out how to do this correctly.但是,当我尝试从验证方法访问它时,该数组显示为未定义,我假设是因为我以与订阅相关的错误顺序执行此操作,但是我无法弄清楚如何正确执行此操作。

Below is the stripped down code which should show what I'm trying to do.下面是精简的代码,它应该显示我正在尝试做的事情。 I've tried it with both of the validator functions.我已经尝试过使用两个验证器功能。 I have also tried moving the formgroup definition into the ngOnInit, and into the actual subscribe function, straight after allUserNames is populated.我还尝试将表单组定义移动到 ngOnInit 中,并在填充完 allUserNames 之后直接移动到实际的订阅功能中。

export class userComponent implements OnInit {

  user: user = new user;
  allUserNames: string[];

  generalForm = new FormGroup({
    userName: new FormControl(
      this.user.name, [
        Validators.required,
        Validators.maxLength(20),
        this.UniqueNameValidator
        //,this.UniqueNameValidator1(this.alluserNames)
      ])
  })

  constructor(private userService: userService) { }

  ngOnInit() {
    this.subscribeUsers();
  }

  subscribeUsers(): void {
    this.getUsers().subscribe((users) => {
      this.allUserNames = Object.keys(users).map(itm => users[itm].name);
    })
  }

  getUsers(): Observable<user[]> {
    return this.userService.getUsers();
  }

  UniqueNameValidator(allUsers: String[]): ValidatorFn {
    return (control: AbstractControl): { [key: string]: boolean } | null => {
      allUsers.forEach((userName) => {
        if (userName === control.value) {
          return { 'notUnique': true };
        }
      });
      return null;
    }
  }

  UniqueNameValidator1(control: AbstractControl): { [key: string]: boolean } | null {
    this.allUserNames.forEach((userName) => {
      if (userName === control.value) {
        return { 'notUnique': true };
      }
    });
    return null;
  }
}

I expect the validate function to compare the input string and return not unique if it gets a match from allUserNames.我希望验证函数比较输入字符串,如果它从 allUserNames 获得匹配项,则返回不唯一。 However I keep getting the following error:但是我不断收到以下错误:

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'forEach' of undefined  

I would really appreciate it if someone could point me in the right direction!如果有人能指出我正确的方向,我将不胜感激!

Thanks.谢谢。

You have a scope issue with this .你有一个范围的问题this If you were to console log this , you would see that it doesn't point to the component, but your function.如果您要控制台记录this ,您会看到它没有指向组件,而是指向您的函数。

This would be a proper place for an async validator as you are doing a http call.当您进行 http 调用时,这将是异步验证器的合适位置。 Also I would suggest to use FormBuilder when building form, so...另外我建议在构建表单时使用FormBuilder ,所以......

generalForm: FormGroup;

constructor(private userService: userService, private fb: FormBuilder) {
  this.generalForm = this.fb.group({
    userName: [this.user.name, 
              [Validators.required, Validators.maxLength(20)], 
              [this.UniqueNameValidator.bind(this)]]
  })
}

Async validators are place as the third argument.异步验证器作为第三个参数放置。 See we are also using bind(this) to get the correct scope of this .见我们还使用bind(this) ,以获得正确的范围this

Then the validator would look something like this:然后验证器看起来像这样:

import { of } from 'rxjs';
import { switchMap } from 'rxjs/operators'

UniqueNameValidator(ctrl: AbstractControl) {
  return this.userService.getUsers().pipe(
      switchMap((users: user[]) => {
        // do stuff, and either return error or "of(null)"
      })
  );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在Angular 6中为反应形式正确实现自定义正则表达式验证器? - How to properly implement custom regex validator for reactive form in Angular 6? 如何以角度形式实现验证器 - How to implement a validator in an Angular Form Angular 2自定义验证器(模板表单)验证 - Angular 2 Custom Validator (Template Form) Validation Angular 6反应形式验证不适用于自定义验证器 - Angular 6 reactive form validation not working with custom validator Angular Form 自定义验证器 http observable 在 http 调用时返回 null - Angular Form custom validator http observable returning null on http call 如何在通用验证器类angular2中实现自定义验证器? - How to implement custom validator in generic validator class angular2? 如何在Dart中使用Angular2实现自定义验证器? - How to implement a custom validator with Angular2 in Dart? 如何在Angular2 / 4/5中实现自定义异步验证器 - How to implement Custom Async Validator in Angular2/4/5 如何在 Angular4 中实现自定义异步验证器 - How to implement Custom Async Validator in Angular4 来自Observable API调用的Angular2模型驱动的表单自定义字段验证 - Angular2 Model-driven form custom field validation from Observable API call
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM