User Authentication using Angular and Django Mat-error from response is not being Displayed

51 Views Asked by At

I’m working on Signup page and I want to handle 'if username already Exists' I have tried to console.log the Error I want to display and it’s been logged on the Console but not appearing on the Mat-error Label.

This is my HTML code:


            <mat-form-field class="example-full-width" appearance="outline">
              <mat-label>Username</mat-label>
              <input matInput formControlName="username" required />
              <mat-error
                *ngIf="registrationForm.get('username')!.hasError('required')"
              >
                Username is <strong>required.</strong>
              </mat-error>
              <mat-error
                *ngIf="
                  registrationForm.get('username')!.hasError('pattern') &&
                  !registrationForm.get('username')!.hasError('required')
                "
              >
                Username should start with
                <strong>a letter or underscore.</strong>
              </mat-error>
              <mat-error
                *ngIf="
                  (registrationForm.get('username')!.hasError('minlength') ||
                    registrationForm.get('username')!.hasError('maxlength')) &&
                  !registrationForm.get('username')!.hasError('required')
                "
              >
                Username should be <strong>between 2 and 12 characters.</strong>
              </mat-error>
              <mat-error *ngIf="usernameTakenError">
                {{ usernameTakenError }}
              </mat-error>
            </mat-form-field>

and That’s my Form Submit Method.

 submitForm(): void {
    if (this.registrationForm.valid) {
      this.http.post('http://localhost:8000/api/register', this.registrationForm.getRawValue())
        .subscribe(
          () => {
            this.router.navigate(['login']);
          },
          (errorResponse) => {
            if (errorResponse.status === 400) {
              const errors = errorResponse.error;
              console.log(errors);
              
              if (errors.email && errors.email.length > 0) {
                this.emailTakenError = errors.email[0];
                console.log(this.emailTakenError);
                
              } else {
                this.emailTakenError = null;
              }

              if (errors.username && errors.username.length > 0) {
                this.usernameTakenError = errors.username[0];
                console.log(this.usernameTakenError);

              } else {
                this.usernameTakenError = null;
              }
            } else {
              // Handle other types of errors (e.g., server errors) here.
            }
          }
        );
    }
  }

How can I handle it and make it display the Error? By the way this is what gets Printed in my Console:

{email: Array(1), username: Array(1)}email: ['user with this email already exists.']username: ['user with this username already exists.'][[Prototype]]: Object signup.component.ts:73 user with this email already exists. signup.component.ts:81 user with this username already exists

.

I tried to remove the Ngif but nothing changed

I am expecting the Error message to be Displayed as Mat-error within username Errors Label but that didn’t happen.

1

There are 1 best solutions below

0
On

I resolved this by using Async validator in Angular.

Like this

username: new FormControl('', {
    updateOn: 'blur',
    validators: [
      Validators.required,
      Validators.pattern(/^[A-Za-z_][A-Za-z0-9_]*$/)
    ],
    asyncValidators: [this.myAsyncValidatorUser.bind(this)]
  }),

That’s my AsyncValidator Function

    myAsyncValidatorUser(
        ctrl: AbstractControl
      ): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
        // ctrl.value <---- this is the current value of the input.
        return this.myHttpCallUser(ctrl.value).pipe(
          map((isAvailable: boolean) => (isAvailable ? null : { backendError: true })),
          catchError(() => of(null)) // Return null when there's a network error
        );
      }

myHttpCallUser(username: string): Observable<boolean> {
    const apiUrl = `http://localhost:8000/api/checkUsername/${username}/`;
    return this.http.get(apiUrl).pipe(
      tap((response: any) => console.log('API Response:', response)),
      map((response: any) => response.available === true),
      catchError((error) => {
        console.error('API Error:', error);
        return of(false);
      })
    );

}

and that’s the Change on HTML

 <mat-error *ngIf="registrationForm.get('username')!.hasError('backendError')">
              user with this <strong> username already exists. </strong>
            </mat-error>