简体   繁体   English

Angular Form 自定义验证器 http observable 在 http 调用时返回 null

[英]Angular Form custom validator http observable returning null on http call

I am trying to setup a form field which will check if a email exists.我正在尝试设置一个表单字段,用于检查电子邮件是否存在。 I have looked at a few examples and have got the validation working, but when I implement the http pipe, map to my services' Observable, it throws it as null?我查看了一些示例并且验证工作正常,但是当我实现 http 管道时,映射到我的服务的 Observable,它抛出它为空? I can assume I am piping to it incorrectly from my service but I am not too sure.我可以假设我从我的服务中错误地管道到它,但我不太确定。

Is anyone able to help me?有谁能帮助我吗?

core.js:6014 ERROR TypeError: Cannot read property 'emailService' of undefined

app.component.ts app.component.ts

export class AppComponent implements OnInit {

  signUpForm: FormGroup;

  constructor(private fb: FormBuilder, private emailService: EmailService) { }

  ngOnInit() {
    this.signUpForm = this.fb.group({
      name: ['', Validators.required],
      email: ['', [Validators.required], [this.validateEmailNotTaken]]
    });
  }

  //Validator for checking if email name is taken or not
  validateEmailNotTaken(control: AbstractControl): Observable<{ [key: string]: any } | null> {

      if (control.value === null || control.value.length === 0) {
        return of(null);
      }
      else {
        return timer(1000).pipe(
          switchMap(() => {


            this.emailService.checkEmailExists(control.value).pipe(
              map(res => {
                //Do what with response
                console.log(res);

                if (!res) {
                  return { taken: true };
                }

                return of(null);
              })
            );


          })
        );
      }


  }

}

email.service.ts电子邮件.service.ts

 interface IServerCheckEmailExists {
    "available": boolean;
}
export interface ICheckEmailExists {
    taken: boolean;
}

@Injectable({ providedIn: 'root' })
export class EmailService {

    constructor(private _http: HttpClient) {
    }

    checkEmailExists(email: string): Observable<ICheckEmailExists[]> {

        var postObject = {"action": "checkEmailExists"};
        return this._http.post<IServerCheckEmailExists[]>("myapiurl/" + email, postObject).pipe(
            map(o => o.map((sp): ICheckEmailExists => ({
                taken: sp.available
            })))
        );
    }
}

Your validateEmailNotTaken method is not getting an instance of the component.您的 validateEmailNotTaken 方法没有获取组件的实例。 You'll need to bind this when creating formGroup.您需要在创建 formGroup 时绑定它。 Modify your code like this:-像这样修改你的代码:-

this.signUpForm = this.fb.group({
  name: ['', Validators.required],
  email: ['', [Validators.required], [this.validateEmailNotTaken.bind(this)]]
});

Please try this and let me know.请试试这个,让我知道。

The only issue that I see in your code is that you're not returning the call to this.emailService.checkEmailExists(control.value) inside the switchMap which you should be doing since you are using {} .我在您的代码中看到的唯一问题是您没有在this.emailService.checkEmailExists(control.value)内返回对this.emailService.checkEmailExists(control.value)switchMap ,因为您使用的是{} Something like this:像这样的东西:

import { Component, OnInit } from "@angular/core";
import {
  FormGroup,
  FormBuilder,
  Validators,
  AbstractControl
} from "@angular/forms";
import { Observable, of, timer } from "rxjs";
import { switchMap, map } from "rxjs/operators";

import { EmailService } from "./email.service";

@Component({
  selector: "my-app",
  templateUrl: `./app.component.html`,
  styleUrls: [`./app.component.css`]
})
export class AppComponent implements OnInit {
  signUpForm: FormGroup;

  constructor(private fb: FormBuilder, private emailService: EmailService) {}

  ngOnInit() {
    this.signUpForm = this.fb.group({
      name: ["", Validators.required],
      email: ["", [Validators.required], [this.validateEmailNotTaken.bind(this)]]
    });
  }

  //Validator for checking if email name is taken or not
  validateEmailNotTaken(
    control: AbstractControl
  ): Observable<{ [key: string]: any } | null> {
    if (control.value === null || control.value.length === 0) {
      return of(null);
    } else {
      return timer(1000).pipe(
        switchMap(() => {
          // RIGHT HERE 👇🏼
          return this.emailService.checkEmailExists(control.value).pipe(
            map(res => {
              //Do what with response
              console.log(res);
              if (res) {
                return of(null);
              }
              return { taken: true };
            })
          );
        })
      );
    }
  }
}

Here's a Working Code Example for your ref.这是您的参考的工作代码示例

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM