Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display http errors globally with Angular 2

Tags:

I want to display popup window with error message of http connection globally for all pages of my application.

Any good way do to it?

like image 540
Yury Scherbakov Avatar asked Jul 15 '16 15:07

Yury Scherbakov


People also ask

How does Angular handle global errors?

One traditional way of handling errors in Angular is to provide an ErrorHandler class. This class can be extended to create your own global error handler. This is also a useful way to handle all errors that occur, but is mostly useful for tracking error logs.

What is Httperrorresponse?

HttpErrorResponselink A response that represents an error or failure, either from a non-successful HTTP status, an error while executing the request, or some other failure which occurred during the parsing of the response.

What is the error component in angular 2?

The ErrorHandler class in Angular 2+ provides a hook for centralized exception handling. The default implementation of ErrorHandler prints error messages to the console. This service is very simple by design. To intercept the error handling we need to write a custom handler.

How do you handle HTTP errors?

When the error occurs in the HTTP Request it is intercepted and invokes the catchError . Inside the catchError you can handle the error and then use throwError to throw it to the service. We then register the Interceptor in the Providers array of the root module using the injection token HTTP_INTERCEPTORS .


2 Answers

You can create a custom component and show list of errors in the popup window by including this custom component. For example you can do this

@Component({
     selector: 'list-errors',
     template: `<ul class="error-messages" *ngIf="errorList">
        <li *ngFor="let error of errorList">
            {{ error }}
        </li> </ul>`
    })
export class ListErrorsComponent {
  formattedErrors: Array<string> = [];

      @Input()
      set errors(errorList: Errors) {
        this.formattedErrors = [];

        if (errorList.errors) {
          for (let field in errorList.errors) {
            this.formattedErrors.push(`${field} ${errorList.errors[field]}`);
          }
        }
      };

      get errorList() { return this.formattedErrors; }
      }

Use this in the popup window where you want to display list of errors

   <list-errors [errors]="errors"></list-errors>

create a error model as such

  export class Errors {
  errors: {[key:string]: string} = {};
  }

set a value of error object and pass this error object to the list-error component

 errors: Errors = //assign your errors to this variable
like image 139
Rahul Kumar Avatar answered Sep 28 '22 03:09

Rahul Kumar


I found solution.

The main idea: use bridge service with EventEmitter.

api.provider.ts

import { Injectable, Output, EventEmitter } from '@angular/core';
import { Http, Headers, Response } from '@angular/http';

@Injectable()
export class ApiProvider {
    private _host: string;

    @Output() errorHandled$ = new EventEmitter();

    constructor(private _http: Http) {
        this._host = "http://localhost:5000";        
    }

    private errorHandler(response: Response): any {        
        if (response.status == 0)
        {            
            this.errorHandled$.emit({
                value: "ERR_CONNECTION_REFUSED"
            });
        }
        return null;
    }

    get(path: string): Promise<any> {
        var headers = new Headers();

        return this._http.get(this._host + path, { headers: headers })
            .toPromise()
            .then(response => {                         
                return response.json();
            })
            .catch((response: Response) => this.errorHandler(response));
    }

    post(path: string, body: string): Promise<any> {
        var headers = new Headers();
        headers.append('Content-Type', 'application/x-www-form-urlencoded');

        return this._http.post(this._host + path, body, { headers: headers })
            .toPromise()
            .then((response: Response) => {
                return response.json();
            })
            .catch((response: Response) => this.errorHandler(response));
    }
}

app.component.ts

import 'rxjs/Rx';
import { Component } from '@angular/core';

import { ApiProvider } from './providers/api.provider';

@Component({
    selector: 'mii-app',
    templateUrl: './app.component.html'
})
export class AppComponent {    
    globalErrors: string[];

    constructor(private _api: ApiProvider) {
        this.globalErrors = [];

        _api.errorHandled$.subscribe(value => { console.log('subscribe'); this.globalErrors.push('error connection.')});          
    }

    clearErrors(): void
    {
        this.globalErrors = [];
    }
}

app.component.html

<div *ngIf="globalErrors.length > 0" class="alert alert-danger fade in">
    <a (click)="clearErrors()" class="close" aria-label="close">&times;</a>
    error...
</div>

We must register our ApiProvider in main.ts to have single instance from dependency injection.

main.ts

/// <reference path="../../typings/globals/core-js/index.d.ts" />

import { bootstrap } from '@angular/platform-browser-dynamic';
import { HTTP_PROVIDERS } from '@angular/http';

import { AppComponent } from './app.component';
import { ApiProvider } from './providers/api.provider';

bootstrap(AppComponent, [
    HTTP_PROVIDERS,
    ApiProvider
])
.catch(err => console.error(err));
like image 30
Yury Scherbakov Avatar answered Sep 28 '22 02:09

Yury Scherbakov