angularformsapiangular6handleerror

Handle errors which are coming from back-end API and show them in angular 6 front-end form


I'm working on a signup form and connected with Laravel back-end API. when I insert data of new customer it successfully send request to back-end and redirect to login page. when I give wrong data or existing data errors should show right bellow to the input box in the signup form. But now it's not showing errors in the form but errors can be shown in console.

onSubmit() {
this.appService.signUp(this.form).subscribe(
     data => this.handleResponse(data),
     error => this.handleError(error)
 );
}

This is my submit button's function and when I comment data => this.handleResponse(data), it will show errors right after the input box as an alert which are coming from the back-end. when the both data and error are in the function errors are not showing in the form. I want to handle errors and as well as pass data to handleResponse function.

sign-up.component.ts

export class SignUpComponent implements OnInit {

 public form = {
   firstName: null,
   lastName: null,
   email: null,
   mobile: null,
   password: null
 };
 public error = [];

constructor(
  private appService: AppService,
  private token: TokenService,
  private router: Router) { }

onSubmit() {
  this.appService.signUp(this.form).subscribe(
     data => this.handleResponse(data),
   // data => console.log(data),
  error => this.handleError(error)
  );
}

handleResponse(data) {
  console.log(data);
  // this.token.handleToken(data.data.accessToken);
  if (data.code === 'SUCCESS') {
    this.router.navigateByUrl('/login');
    }
}

handleError(code) {
  this.error = code.data;
   console.log(code.data);
}

ngOnInit() {
}

}

sign-up.component.html

<div class="mt-4 col-8 offset-2">
<div class="card">
 <div class="card-header">Register Here</div>
 <div class="card-body">
  <form #signupForm =ngForm (ngSubmit)="onSubmit()">
    <div class="form-group row">
      <label for="inputFirstName3" class="col-sm-2 col-form-label">First Name</label>
      <div class="col-sm-10">
        <input type="text" name="firstName" class="form-control" id="inputFirstName3" placeholder="First Name" [(ngModel)]="form.firstName" required>
        <div class="alert alert-danger" [hidden]="!error.firstName">{{error.firstName}}</div>
      </div>
    </div>

    <div class="form-group row">
      <label for="inputLastName3" class="col-sm-2 col-form-label">Last Name</label>
      <div class="col-sm-10">
        <input type="text" name="lastName" class="form-control" id="inputLastName3" placeholder="Last Name" [(ngModel)]="form.lastName" required>
        <div class="alert alert-danger" [hidden]="!error.lastName">{{error.lastName}}</div>
      </div>
    </div>

    <div class="form-group row">
      <label for="inputEmail3" class="col-sm-2 col-form-label">Email</label>
      <div class="col-sm-10">
        <input type="email" name="email" class="form-control" id="inputEmail3" placeholder="Email" [(ngModel)]="form.email" required>
        <div class="alert alert-danger" [hidden]="!error.email">{{error.email}}</div>
      </div>
    </div>

    <div class="form-group row">
      <label for="inputMobile" class="col-sm-2 col-form-label">Mobile</label>
      <div class="col-sm-10">
        <input type="text" name="mobile" class="form-control" id="inputMobile" placeholder="Mobile" [(ngModel)]="form.mobile" required>
        <div class="alert alert-danger" [hidden]="!error.mobile">{{error.mobile}}</div>
      </div>
    </div>

    <div class="form-group row">
      <label for="inputPassword3" class="col-sm-2 col-form-label">Password</label>
      <div class="col-sm-10">
        <show-hide-password size="small" icon="icon-eye" btnStyle="default" [btnOutline]="false">
          <input type="password" name="password" class="form-control" id="inputPassword3" placeholder="Password" [(ngModel)]="form.password" required>
        </show-hide-password>
        <div class="alert alert-danger" [hidden]="!error.password">{{error.password}}</div>
      </div>
    </div>

    <div class="form-group row">
      <div class="col-sm-10 offset-2">
        <button type="submit" class="btn btn-primary" [disabled]="!signupForm.valid">Sign up</button>

        <a routerLink="/login" class="btn btn-info float-right">Sign in</a>
      </div>
    </div>
  </form>
</div>

app.service.ts

import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http';

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

 private baseUrl = 'http://dev.api.prestotestlabs.com/api';
 constructor(private http: HttpClient) { }

 signUp(data) {
  return this.http.post(`${this.baseUrl}/customers`, data);
 }

login(data) {
  return this.http.post(`${this.baseUrl}/login`, data);
 }
}

token.service.ts

import { Injectable } from '@angular/core';

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

private iss = {
  login: 'http://dev.api.prestotestlabs.com/api/login',
  signup: 'http://dev.api.prestotestlabs.com/api/customers',
};
constructor() { }

handleToken(token) {
  this.set(token);
  // console.log(this.isValid());
}

set(token) {
  localStorage.setItem('token', token);
  // console.log(this.get());
}

get() {
 return localStorage.getItem('token');
}

remove() {
  localStorage.removeItem('token');
}

isValid() {
  const token = this.get();
  if (token) {
    const payload = this.payload(token);
  if (payload) {
    return Object.values(this.iss).indexOf(payload.iss) > -1 ? true : false;
   }
  }
  return false;
 }

payload(token) {
  const payload = token.split('.')[1];
  return this.decode(payload);
}
decode(payload) {
  return JSON.parse(atob(payload));
}
loggedIn() {
  return this.isValid();
 }
}

Solution

  • You can use Try Catch Error Handling to handle error status or you can use the response of HttpClient request's subscribe as bellow. I'm not sure weather this is the most suitable answer, but it gives what I wanted.

    onSubmit() {
     this.toastrService.success('', 'Processing...', {timeOut: 9500});
     this.registerSubs = this.userAuthenticationService.register(this.model)
      .catch((err: any) => {
        this.toastrService.toasts.forEach(toast => {
          this.toastrService.clear(toast.toastId);
        });
    
        return Observable.empty<T>();
      }).
    subscribe(response => {
        this.toastrService.toasts.forEach(toast => {
          this.toastrService.clear(toast.toastId);
        });
      if (response !== null && response.code === 'SUCCESS') {
        this.toastrService.success('One more step to complete registration!');
        this.viewService.headerChange.next(true);
        this.router.navigateByUrl('/otp-verification');
        window.scrollBy(0, 10);
        this.viewService.closeSideMenu.next();
      } else if (response !== null && response.code === 'VALIDATION_FAILED') {
        this.toastrService.error(this.generateErrorMessages(response.data));
      } else if (response !== null && response.code === 'FAIL'){
        this.toastrService.error(response.message);
      }else {
      }
    });
    }
    
    
    generateErrorMessages(errors: any[]) {
    let errorString = '';
    if ((<any>errors).email !== null && typeof((<any>errors).email) !== 'undefined') {
      errorString += (<any>errors).email;
    }
    if ((<any>errors).mobile !== null && typeof((<any>errors).mobile) !== 'undefined') {
      errorString += (<any>errors).mobile;
    }
    
    return errorString;
    }