typescript 为什么我的自定义验证程序不更新FormControl?

oyjwcjzk  于 2022-12-24  发布在  TypeScript
关注(0)|答案(2)|浏览(137)

我有一个Redux-SPA,它的消息传递系统有邮箱(基本上只是文件夹)。当用户想创建一个新邮箱(文件夹)时,会显示一个对话框,用户可以在其中输入新邮箱名。为了防止不必要的API调用,我查看状态,看看邮箱/文件夹是否已经存在。如果是,我想使表单无效,并禁用"创建"按钮。
我已经确保函数通过tap()返回正确的值。如果控件为空,则会正确地使其无效,因此默认验证器工作正常。只是我的自定义验证器不工作。
我的错误在哪里?我可以尝试进一步调试什么?
这是我的代码:

@Component({
  selector: 'app-new-mailbox-dialog',
  templateUrl: 'new-mailbox-dialog.component.html',
})
export class NewMailboxDialogComponent implements OnInit {
  formControl: FormControl = new FormControl('', [Validators.required], this.mailboxNameExists.bind(this));

  constructor(
    public dialogRef: MatDialogRef<NewMailboxDialogComponent>,
    private messagingFacade: MessagingFacade
  ) {}

  ngOnInit() {}

  onNoClick(): void {
    this.dialogRef.close();
  }

  mailboxNameExists(control: FormControl): Observable<ValidationErrors | null> {
    return this.messagingFacade.getMailboxesList$.pipe(
      tap(() => console.log(control.value)),
      map(names => names.find(mailbox => mailbox.designation === control.value)),
      map(exists => exists ? { mailboxNameExists: true } : null)
      tap(value => console.log(value)),
    );
  }
}

这是名为"Test"

的现有邮箱的控制台输出

tpxzln5u

tpxzln5u1#

我通常按如下方式编写AsyncValidatorFn流/方法:

validator(): AsyncValidatorFn {
    return (control: AbstractControl): Observable<ValidationErrors | null> => {
      if (!control.value || control.pristine) {
        return of(null);
      }
      
      return control.valueChanges.pipe(
        debounceTime(300),
        distinctUntilChanged(),
        take(1),
        switchMap(value => {
          return this.messagingFacade.getMailboxesList$;
        }),
        catchError(err => of(null)),
        map(response => {
            return response ? { error: true } : null;
          }),
        finalize(() => {
          control.markAsTouched();
          this.ref.markForCheck();
        })
      );
    };
  }

不确定你是否需要最终确定,我通常会对检测策略进行此操作。
此外,在模板中,您没有显示我通常检查触摸和无效沿着错误,以显示错误消息。

f0brbegy

f0brbegy2#

需要调用可观察对象的“complete”方法来触发验证。
假设您正在使用一个subject或类似的observable,其中默认情况下不调用完整的方法,流保持打开,因此不会触发验证。
解决此问题的几种方法包括

1.使用of方法,默认情况下调用complete方法。

消息正面TS:

mailboxesList = [{designation: 'test'}]
getMailboxesList$ = of(this.mailboxesList)
2.手动调用可观察对象中的complete方法。

消息正面TS:

mailboxesList = [{designation: 'test'}]
getMailboxesList$ = new Observable((subscriber) => {
    subscriber.next(this.mailboxesList);
    subscriber.complete();
  });
3.使用take操作符取消订阅,这将结束流并触发验证。

组件TS:

return this.messagingFacade.getMailboxesList$.pipe(
  map((names: any[]) =>
    names.find((mailbox) => mailbox.designation === control.value)
  ),
  map((exists) => (exists ? { mailboxNameExists: true } : null)),
  take(1)
);

相关问题