7

I'm trying to do the following in Angular 2 (typescript): For each error (especially errors from the backend server) - present the error to the user (in the UI) - in the main component (mainly since I do't want to write same code in each component).

Is it a simple way to do it? I guess what I need is a way to set an "error" member in the main component? How do I do it if I override ExceptionHandler?

thanx, Pavel.

pavelb
  • 83
  • 1
  • 1
  • 5
  • See http://stackoverflow.com/questions/38882969/change-in-angular2-rc5-exceptionhandler and https://angular.io/docs/ts/latest/api/core/index/ExceptionHandler-class.html You should be aware that not catching exceptions locally can leave your component in an undefined state. You might need to invoke change detection afterwards explicitely. See for example http://stackoverflow.com/questions/37793276/angular-2-custom-exceptionhandler-change-detection-lag/37793791#37793791 – Günter Zöchbauer Aug 16 '16 at 20:07
  • Hi Günter, My question is how do I make the ExceptionHandler change some state in the main app component (to present an error message in the UI)? – pavelb Aug 16 '16 at 20:30
  • You can use a shared service where you update the state from the exception handler or emit events using observables and a component that updates the DOM (show error information) depending on the info from that service. – Günter Zöchbauer Aug 16 '16 at 20:42
  • Hi Günter, If I understand correctly, you suggest: In ExceptionHandler - call MyService.setErrorState(true), then in main component add ngif calling MyService.getErrorState(). But who will call MyService.setErrorState(false) when moving to next page? – pavelb Aug 17 '16 at 07:06
  • That depends on your requirements. Perhaps you want to wait until the user clicks "dismiss" or just a timeout so the message disappears after 10 seconds, ... – Günter Zöchbauer Aug 17 '16 at 07:43
  • thanx Günter. I eventually decided to do an other thing (handle the error on component level), and there I have no problem - I can clear it in onInit(). – pavelb Aug 17 '16 at 12:31

1 Answers1

18
  1. Create NotificationService in shared directory

    import { Injectable } from '@angular/core';
    import { Message } from 'primeng/primeng';
    
    @Injectable()
    export class NotificationService {
        message: Message[];
    
        constructor() {
            this.message = [];
        }
    
        success(detail: string, summary?: string): void {
            this.message.push({
                severity: 'success', summary: summary, detail: detail
            });
        }
    
        info(detail: string, summary?: string): void {
            this.message.push({
                severity: 'info', summary: summary, detail: detail
            });
        }
    
        warning(detail: string, summary?: string): void {
            this.message.push({
                severity: 'warn', summary: summary, detail: detail
            });
        }
    
        error(detail: string, summary?: string): void {
            this.message.push({
                severity: 'error', summary: summary, detail: detail
            });
        }
    }
    
  2. create a custom ExceptionHandler (ErrorHandler in RC 6) in shared directory

    import { ErrorHandler, Inject } from '@angular/core';
    import { NotificationService } from './notification.service';
    
    
    export class CustomErrorHandler implements ErrorHandler {
    
        constructor(@Inject(NotificationService) private notificationService: NotificationService) {
        }
    
        handleError(error: any): void {
            this.showErrorInConsole(error);
            setTimeout(() => 
                this.notificationService.error(error.json().Message), 1);
        }
    
        private showErrorInConsole(error: any) :void {
            if (console && console.group && console.error) {
                console.group("Error Log");
                console.error(error);
                console.error(error.message);
                console.error(error.stack);
                console.groupEnd();
            }
        }
    }
    
  3. update AppModule for overriding default error handler

    import { GrowlModule } from 'primeng/primeng';
    ...
    import { NotificationService } from './shared/notification.service';
    import { CustomErrorHandler } from './shared/custom-error-handler';
    
    @NgModule({
        imports: [
            ...,
            GrowlModule // prime ng notification
        ],
        declarations: [
            ...
        ],
        providers: [
            ...,
            NotificationService, // added
            { provide: ErrorHandler, useClass: CustomErrorHandler } // overrride default error handler
        ],
        bootstrap: [AppComponent]
    })
    export class AppModule { }
    
  4. finally in AppComponent:

    import { Component } from '@angular/core';
    import { Message } from 'primeng/primeng';
    import { NotificationService } from './shared/notification.service';
    
    
    @Component({
        selector: 'my-app',
        template: `
            <p-growl [value]="getMessages()"></p-growl>
        `
    })
    export class AppComponent{
        constructor(private notification: NotificationService) {
        }
    
        getMessages(): Message[] {
            return this.notification.message;
        }
    }
    
Hadi Farhadi
  • 1,773
  • 2
  • 16
  • 33
  • In case it helps anyone, I had to use the following in my template: in order to get the binding to work correctly, notificationService being made a public member of the component. – Chris Peacock Feb 28 '18 at 13:03
  • Note that `GrowlModule` has now been deprecated. Use Toast instead. https://github.com/primefaces/primeng/issues/8328 – gavxn Dec 10 '19 at 11:15
  • Also worth using PrimeNG `MessageService` . Example: https://github.com/primefaces/primeng/blob/91114a019cda073634f093ffd16511d375825f79/src/app/showcase/components/toast/toastdemo.ts – gavxn Dec 12 '19 at 15:47