N
N
nekritik2019-07-12 11:03:18
Angular
nekritik, 2019-07-12 11:03:18

Angular 8: When I try to inject a validator into a component's constructor, Angular redirects me to the main page without throwing any errors. Why?

The problem seems to be quite simple, but I can't find a solution. There is a registration-page.component.ts component that simply displays a form with one field - email

import { Component, OnInit } from '@angular/core';
import {FormControl, FormGroup, Validators} from '@angular/forms';
import {EmailExistsValidator} from '../shared/services/my.validators';

@Component({
  selector: 'app-registration-page',
  templateUrl: './registration-page.component.html',
  styleUrls: ['./registration-page.component.css']
})
export class RegistrationPageComponent implements OnInit {

  form: FormGroup
  constructor() { }

  ngOnInit() {
    this.form = new FormGroup(
      {
        email: new FormControl(null, [Validators.required, /*this.emailExistsValidator.validate.bind(this.emailExistsValidator)*/])
      });
  }

}

Routing is configured in such a way that when you go to localhost:4200/registration , a form with an email field is displayed.
For my only field so far, email, I need to make a self-written validator that will check if there is already a registered user with this address. I wrote the validator using this and this examples from the official angular repository.
Here is the validator
import {EmailService} from './email.service';
import {catchError, map} from 'rxjs/operators';
import {AbstractControl, AsyncValidator, ValidationErrors} from '@angular/forms';
import {Observable} from 'rxjs';
import {Injectable} from '@angular/core';

@Injectable({ providedIn: 'root' })
export class EmailExistsValidator implements AsyncValidator {
  constructor(private emailService: EmailService) {}

  validate(
    ctrl: AbstractControl
  ): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
    return this.emailService.Is_email_exists(ctrl.value).pipe(
      map(isTaken => (isTaken ? { uniqueAlterEgo: true } : null)),
      catchError(() => null)
    );
  }
}

Following the example I linked earlier, the validator needs to be injected - I change only one line in the registration-page.component.ts file,
constructor() { }
to
constructor(private emailExistsValidator: EmailExistsValidator) { }

and after that I can't access localhost:4200/registration - I'm redirected to the main page. There are no errors in the terminal, it seems.
What could be the issue here?
I tried not to litter my question with source codes, but if there is not enough information to solve the problem, please speak up and I will add additional source codes to the question

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anton Shvets, 2019-07-12
@nekritik

I don’t know why you are being redirected, apparently the error is being intercepted somewhere. ngOnInit in the component should throw an exception for you.
At first glance, I see:
1. async validators are passed in the third parameter of the FormControl, and you have it in the second, along with simple validators.
Further, I don’t see the point of making a validator through a service that implements AsyncValidator, in the examples it is used to create directives. In your example, a validator will be passed to the directive using the NG_ASYNC_VALIDATORS token.
You can probably use AsyncValidator for a component (of the type that implements ControlValueAccessor), but you will also need to provide it by specifying the token (but this is not accurate). Usually there is simply no need for this.
For simple async validation, you can use a validator factory function that takes dependencies from a component.
Like this https://ng-run.com/edit/DDaBjbxR39I7DIImTg0n
Yes, and more. Your validator will make requests for each character entered in the form. To avoid this, you need to specify updateOn.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question