如何实现形式,即验证逻辑,需要从可观察数据上的自定义验证

问题描述 投票:1回答:1

我想实现窗体上的自定义验证,这将检查表单输入,并将其与值的阵列,以确保输入值是唯一的。用于比较的阵列来自于可观察到的。然而,当我试图从验证方法访问阵列表现为不确定的,我假设,因为我正在做错误的顺序相对于认购,不过,我可以不知道如何正确地做到这一点。

下面是精简代码,应该表现出什么,我试图做的。我已经与这两者的验证功能,试了一下。我也曾尝试formgroup定义移动到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;
  }
}

我希望验证功能比较输入字符串,返回不是唯一的,如果它从allUserNames获得匹配。不过,我不断收到以下错误:

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

我真的很感激,如果有人可以在正确的方向指向我!

谢谢。

angular typescript angular6 angular2-observables
1个回答
1
投票

你有一个this范围的问题。如果你到控制台登录this,你会看到,它并不指向组件,但你的函数。

这将是一个异步验证一个适当的地方,你在做一个HTTP调用。此外,我建议建立表格时使用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)]]
  })
}

异步验证的地方作为第三个参数。见我们还使用bind(this)得到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)"
      })
  );
© www.soinside.com 2019 - 2024. All rights reserved.