簡體   English   中英

Angular Reactive 表單不等待自定義異步驗證器

[英]Angular Reactive forms don't wait for custom async validators

我的 angular-CLI 應用程序中有一個登錄組件。 我有字段電子郵件和密碼。 我創建了兩個自定義驗證 => 一個用於檢查用戶是否存在,另一個用於檢查密碼是否與用戶匹配。 我檢查了內置驗證器的工作情況,例如必填字段和有效電子郵件。 他們工作得很好。 問題是我的自定義驗證器僅在調用提交后才顯示錯誤。 反應式表單不會等待自定義異步驗證器解析。

這是我的代碼:

import {Component, OnInit} from '@angular/core';
import {FormGroup, FormBuilder, Validators} from '@angular/forms';
import {AuthService} from '../auth.service';
import {noUser, pwdMisMatch} from '../validators';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {

  form: FormGroup;
  submitted = false;
  returnUrl: string;

  constructor(private formBuilder: FormBuilder, public authService: AuthService) {
    this.form = this.formBuilder.group({
        email: ['', [Validators.required, Validators.email]],
        password: ['', Validators.required],
      },
      {
        validators: [noUser(authService, 'email'), pwdMisMatch(authService, 'email', 'password')]
        , updateOn: 'blur'
      }
    );
  }

  ngOnInit() {
    this.returnUrl = '/dashboard';
    this.authService.logout();
  }

  get f() {
    return this.form.controls;
  }

  onSubmit() {
    this.submitted = true;

    // stop here if form is invalid
    if (this.form.invalid) {
      return;
    } else {
      alert('Success');
    }
  }

}

這是我的自定義驗證器文件:

import {FormGroup} from '@angular/forms';
import {AuthResponse, AuthService} from './auth.service';

export function MustMatch(controlName: string, matchingControlName: string) {
  return (formGroup: FormGroup) => {
    const control = formGroup.controls[controlName];
    const matchingControl = formGroup.controls[matchingControlName];

    if (matchingControl.errors && !matchingControl.errors.mustMatch) {
      // return if another validator has already found an error on the matchingControl
      return;
    }

    // set error on matchingControl if validation fails
    if (control.value !== matchingControl.value) {
      matchingControl.setErrors({ mustMatch: true });
    } else {
      matchingControl.setErrors(null);
    }
  };
}

export function userExist(authservice: AuthService, controlName: string) {
  return (formGroup: FormGroup) => {
    const control = formGroup.controls[controlName];

    if (control.errors && !control.errors.CheckUser) {
      // return if another validator has already found an error on the matchingControl
      return;
    }

    // set error on matchingControl if validation fails
    authservice.checkUser(control.value).subscribe((res: AuthResponse) => {
      if (res.ok) {
        control.setErrors({ userExist: true });
      } else {
        control.setErrors(null);
      }
    });
  };
}

export function noUser(authService: AuthService, controlName: string) {
  return (formGroup: FormGroup) => {
    const control = formGroup.controls[controlName];

    if (control.errors && !control.errors.noUser) {
      // return if another validator has already found an error on the matchingControl
      return;
    }

    // set error on matchingControl if validation fails
    authService.checkUser(control.value).subscribe((res: AuthResponse) => {
      if (!res.ok) {
        control.setErrors({ noUser: true });
      } else {
        control.setErrors(null);
      }
    });
  };
}

export function pwdMisMatch(authService: AuthService, controlName: string, secureControlName: string) {
  return (formGroup: FormGroup) => {
    const control = formGroup.controls[controlName];
    const secureControl = formGroup.controls[secureControlName];

    if (control.errors || secureControl.errors && !secureControl.errors.pwdMisMatch) {
      // return if another validator has already found an error on the matchingControl
      return;
    }

    // set error on matchingControl if validation fails
    authService.verifyPassword(control.value, secureControl.value).subscribe((res: AuthResponse) => {
      if (!res.ok) {
        secureControl.setErrors({ pwdMisMatch: true });
      } else {
        control.setErrors(null);
      }
    });
  };
}

我試過這個答案,但問題沒有解決。 請幫忙。

更新:我的角度回購

Angular customValidator 函數應該返回錯誤或空值才能工作。

FormGroup 具有掛起狀態,您可以使用它來檢查異步驗證器是否已完成。

嘗試這個:

export function noUser(authService: AuthService, controlName: string) {
  return (formGroup: FormGroup) => {
    const control = formGroup.controls[controlName];

    if (control.errors && !control.errors.noUser) {
      // return if another validator has already found an error on the matchingControl
      return;
    }

    // set error on matchingControl if validation fails
    authService.checkUser(control.value).subscribe((res: AuthResponse) => {
      if (!res.ok) {
        return { noUser: true };
      } else {
        return null;
      }
    });
  };
}

export function pwdMisMatch(authService: AuthService, controlName: string, secureControlName: string) {
  return (formGroup: FormGroup) => {
    const control = formGroup.controls[controlName];
    const secureControl = formGroup.controls[secureControlName];

    if (control.errors || secureControl.errors && !secureControl.errors.pwdMisMatch) {
      // return if another validator has already found an error on the matchingControl
      return;
    }

    // set error on matchingControl if validation fails
    authService.verifyPassword(control.value, secureControl.value).subscribe((res: AuthResponse) => {
      if (!res.ok) {
        rerurn { pwdMisMatch: true };
      } else {
        return null;
      }
    });
  };
}

 onSubmit() {
        this.submitted = true;

        // stop here if form is invalid
        if (this.form.pending && this.form.invalid) {
          return;
        } else {
          alert('Success');
        }
      }

也許您應該將其標識為異步驗證器,如下所示:

constructor(private formBuilder: FormBuilder, public authService: AuthService) {
    this.form = this.formBuilder.group(
        {
            email: ['', [Validators.required, Validators.email]],
            password: ['', Validators.required],
        },
        {
            asyncValidators: [noUser(authService, 'email'), pwdMisMatch(authService, 'email', 'password')]
            , updateOn: 'blur'
        }
    );
}

您的異步驗證函數不返回 Promise 或 Observable 的問題

從角度文檔:

異步驗證器:接受控件實例並返回 Promise 或 Observable 的函數,該 Promise 或 Observable 隨后會發出一組驗證錯誤或 null。 您可以在實例化 FormControl 時將它們作為第三個參數傳入

不要在這里使用訂閱:

authservice.checkUser(control.value).subscribe()

改用 pipe() 轉換:

authservice.checkUser(control.value). pipe(map(res => res && res.ok ? ({ userExist: true }) : null )) 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM