Ngx-toastr: Using toast in ErrorHandler not working (per directions in FAQ)

Created on 29 Jan 2018  路  5Comments  路  Source: scttcper/ngx-toastr

ngx toast version: 8.1.1;
angular version: 5.0.0;
rxjs version: 5.5.2

I've verified toastr works in the app, just can't seem to get it to work as part of my custom error class that extends ErrorHandler.

My class is defined as:

import { ErrorHandler, Inject, Injector} from '@angular/core';
import { ToastrService } from 'ngx-toastr';

export class AppErrorHandler implements ErrorHandler {
    constructor(@Inject(Injector) private injector: Injector) { }

    private get toastrService(): ToastrService {
        return this.injector.get(ToastrService);
    }

    public handleError(error: any): void {
        this.toastrService.error('Show me an error message');
        throw error;
    }
}

and then in root module:

import { AppErrorHandler } from './config/error-handling.config';
@NgModule({
  // ... other imports, declarations, etc.
  providers: [
    { provide: ErrorHandler, useClass: AppErrorHandler },
    // ... other providers
  ]
})
export class AppModule {}

In my component I'm calling a http method with some invalid parameters and then: throw error in the error handler.

.subscribe(
response => { console.log(response) }',
error => { throw error; }
)

I can see my custom error handler class is called but no toast appears. The instructions in the FAQ seem to be a response to ngx-toastr v5.2.4, is there possibly something that was introduced that changes how this should be done?

Most helpful comment

It should work. In a lot of cases the error handler will run outside of Angular's zone. This causes toasts not to behave correctly since change detection doesn't run on it. Turn on onActivateTick in the error handler to ensure that the toast is running inside Angular's zone:

@Injectable()
export class GlobalErrorHandler extends ErrorHandler {

    constructor(
        @Inject(Injector) private readonly injector: Injector
    ) {
        super(true);
    }

    handleError(error) {
        console.log("Handling error: " + error);

        this.toastrService.error("testing", null, { onActivateTick: true })

        super.handleError(error);
    }

    /**
     * Need to get ToastrService from injector rather than constructor injection to avoid cyclic dependency error
     * @returns {} 
     */
    private get toastrService(): ToastrService {
        return this.injector.get(ToastrService);
    }

}

This plunker is an example of how to get it to work (using ngx-toastr 8.1.1):
https://plnkr.co/edit/0pWbqD?p=preview

All 5 comments

It should work. In a lot of cases the error handler will run outside of Angular's zone. This causes toasts not to behave correctly since change detection doesn't run on it. Turn on onActivateTick in the error handler to ensure that the toast is running inside Angular's zone:

@Injectable()
export class GlobalErrorHandler extends ErrorHandler {

    constructor(
        @Inject(Injector) private readonly injector: Injector
    ) {
        super(true);
    }

    handleError(error) {
        console.log("Handling error: " + error);

        this.toastrService.error("testing", null, { onActivateTick: true })

        super.handleError(error);
    }

    /**
     * Need to get ToastrService from injector rather than constructor injection to avoid cyclic dependency error
     * @returns {} 
     */
    private get toastrService(): ToastrService {
        return this.injector.get(ToastrService);
    }

}

This plunker is an example of how to get it to work (using ngx-toastr 8.1.1):
https://plnkr.co/edit/0pWbqD?p=preview

That definitely did the trick! Appreciate your help :)

well i faced the same problem then applied the code as above. But the toster message shows only after i click twice

@yarrgh thanks for your solution! I'll add this alternative which is more explicit for me

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

constructor(private injector: Injector, private zone: NgZone) {}

handleError(e: any) {
  this.zone.run(() => this.toastr.error('Something went wrong!'));
}

See: https://github.com/scttcper/ngx-toastr/issues/804 for cyclic dependency issues with Angular 9

Was this page helpful?
0 / 5 - 0 ratings