Angular сервис всегда неопределен при вызове в asyn c валидатор - PullRequest
0 голосов
/ 26 января 2020

Я уже посмотрел много других SO вопросов, но ни один из них не сработал.

Я пытаюсь создать asyn c валидатор, который проверяет, существует ли уже введенное имя пользователя. Но всякий раз, когда я вводю букву в поле ввода, я получаю сообщение об ошибке, что мой userService экземпляр равен undefined.

. Ниже приводится мой UserService:

export interface UsernameCheck {
  info: string,
  usernameAvailable: boolean;
}

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private apiUrl = 'http://localhost:5001/project-f-angular/us-central1';

  constructor(
    private http: HttpClient
  ) { }

  checkUsername(username: string) {
    const params = new HttpParams().set('username', username);

    return this.http.get<UsernameCheck>(`${this.apiUrl}/checkUsername`, {params});
  }
}

Запрос http указывает на локально работающий эмулятор облачных функций Firebase.

Это мой компонент, в котором я его использую:

export class SignUpComponent implements OnInit {
  signUpForm: FormGroup;

  constructor(
    private userService: UserService,
    private formBuilder: FormBuilder) {
  }

  ngOnInit() {
    this.signUpForm = this.formBuilder.group({
      username: [null, Validators.required, this.existingUsername],
      email: [null, [Validators.required, Validators.email]],
      password: [null, Validators.required],
      confirmPassword: [null, Validators.required]
    });
  }

  existingUsername(control: FormControl): Promise<any> | Observable<any> {
    console.log(control.value);
    return this.userService.checkUsername(control.value)
      .pipe(
        map(res => {
          return res.usernameAvailable ? null : {existingUsername: true};
        })
      );
  }
}

Это ошибка, которую я получаю после ввода первой буквы в поле ввода:

ERROR TypeError: Cannot read property 'userService' of undefined
    at existingUsername (sign-up.component.ts:45)
    at forms.js:1492
    at Array.map (<anonymous>)
    at _executeAsyncValidators (forms.js:1488)
    at FormControl.asyncValidator (forms.js:1446)
    at FormControl._runAsyncValidator (forms.js:4100)
    at FormControl.updateValueAndValidity (forms.js:4053)
    at FormControl.setValue (forms.js:4692)
    at updateControl (forms.js:3299)
    at DefaultValueAccessor.onChange (forms.js:3271)

Я также добавил свой Сервис к app.module.ts под providers.

Если я подпишусь на userService внутри ngOnInit, мой метод будет работать так, как нужно, и вернет правильный ответ.

Я новичок в реактивных формах и валидаторах.

Итак, кто-нибудь знает, что я делаю неправильно?

1 Ответ

1 голос
/ 26 января 2020

Вам нужно от bind до this, чтобы передать правильный контекст в валидатор.

this.signUpForm = this.formBuilder.group({
   username: [null, Validators.required, this.existingUsername.bind(this)],  // <--
   email: [null, [Validators.required, Validators.email]],
   password: [null, Validators.required],
   confirmPassword: [null, Validators.required]
});

Вот пример stackblitz , демонстрирующий решение.

Надеюсь, это поможет.

...