Angular 2 RC 2 How to Embed a Router in a Custom ExceptionHandler

I am using Angular 2 RC2. I need to inject an Angular 2 router into my custom ExceptionHandler class. However, I get the following error:

Error: Error: Cannot resolve all parameters for "ErrorHandler" (?). Make sure that all parameters are decorated using Inject or have valid type annotations and that the "ErrorHandler" is decorated with Input.

I tried to decorate a private router: Router with @Inject to no avail. I use typescript, so I don't think I need the @Inject attribute.

My custom ExceptionHandler is as follows

import { ExceptionHandler } from '@angular/core'; import { Router } from '@angular/router'; export class ErrorHandler extends ExceptionHandler{ constructor( private router: Router ){ super(null, null); } call(error, stackTrace = null, reason = null) { console.log(error); this.router.navigate(['/error']); } } 

My main.ts looks like this

 import { bootstrap } from '@angular/platform-browser-dynamic'; import { AppComponent } from './app.component'; import { provide, ExceptionHandler } from '@angular/core'; import { ErrorHandler } from './error-handler/error-handler'; import { HTTP_PROVIDERS } from '@angular/http'; import { ROUTER_PROVIDERS } from '@angular/router'; bootstrap(AppComponent, [ HTTP_PROVIDERS, ROUTER_PROVIDERS, provide(ExceptionHandler, {useClass: ErrorHandler}) ]); 

Why am I getting this error? Is an injector injectable when during an instance of an ExceptionHandler?

Full source code is available here.

https://github.com/harindaka/angular2-seed-typescript/tree/b368315ce6608085f3154a03bc53f0404ce16495

+4
angular angular2-routing
Jun 17 '16 at 10:46 on
source share
6 answers

See: ErrorHandler class. You can add an Injectable decorator to achieve DI too!

 import { ErrorHandler, Injectable } from '@angular/core'; @Injectable() export class GlobalErrorHandler implements ErrorHandler { private myService: MyService; constructor(private injector: Injector) { this.myService = injector.get(MyService); } handleError(error) { alert('Bad things happening'); } } @NgModule({ providers: [ { provide: ErrorHandler, useClass: GlobalErrorHandler } ] }) export class AppModule { } 

Note. The answers above use an ExceptionHandler , which is removed in the final version in favor of ErrorHandler .

+4
Feb 03 '17 at 19:30
source share

Maybe late for the party, but it works for me (Angular 2 RC4):

 import { Injectable, Injector, ExceptionHandler } from '@angular/core'; import { Router } from '@angular/router'; @Injectable() export class AppExceptionHandler extends ExceptionHandler { private router; injector: Injector; constructor(injector: Injector) { super(null, null); this.injector = injector; } call(exception: any, stackTrace?: any, reason?: string): void { if (this.router == null) { this.router = this.injector.get(Router); } // do something with the error such as spitting out to console: console.log('exception:', exception); console.log('stackTrace:', stackTrace); console.log('reason:', reason); // navigate to custom error page (defined in your routes) this.router.navigate(['error']); } } 

And then in your main.ts:

 bootstrap(AppComponent, [ HTTP_PROVIDERS, APP_ROUTER_PROVIDERS, provide(ExceptionHandler, { useClass: AppExceptionHandler })] ) 
+3
Sep 03 '16 at 10:28
source share

ExceptionHandler update has been renamed to ErrorHandler stack overflow

orgiginal

I guess this is caused by circular addiction. You can get around by injecting an injector and get a router imperatively:

 export class ErrorHandler extends ExceptionHandler{ private router: Router constructor(inject:Injector){ this.router = injector.get(Router); super(null, null); } call(error, stackTrace = null, reason = null) { console.log(error); this.router.navigate(['/error']); } } 
+2
Jun 17 '16 at 10:49 on
source share

This is a fairly simple task - to enter the class, you need to make the class injectable . Sounds familiar, right?

If you add @Injectable() at the beginning of your ErrorHandler class, it should work.

 import { ExceptionHandler, Injectable } from '@angular/core'; import { Router } from '@angular/router'; @Injectable() export class ErrorHandler extends ExceptionHandler{ [...] } 
0
Jun 17 '16 at 10:50
source share

just a similar problem arose and solved it like this (using this in the array of application module providers):

 { provide: ExceptionHandler, useFactory: (router) => { return new ErrorHandler(router); }, deps: [Router] } 
0
Aug 25 '16 at 16:55
source share

So, today I came across something similar. My situation is a little different, I expanded Http, for which I need Router. However, ErrorHandler also needed Http. Using the method above with Factories, I thought I could just enter Http in the ErrorHandler. I found that when ErrorHandler caused dependency injection in the constructor for Http, the router did not exist (and it did not have any other necessary context).

So, I have an injector to get an instance during a function call, and not in the constructor. That when the injector is really trying to get Http (in a call), it is already created in the appropriate context.

CustomErrorHandler.ts:

 import { ErrorHandler, Injector } from '@angular/core'; import { Http } from '@angular/http'; import { environment } from 'environments/environment'; export class CustomErrorHandler extends ErrorHandler { private http: Http; constructor(private injector: Injector) { super(); // Calling this.injector.get(Http); here resulted in a null Router window.onerror = (msg: any, url: any, line: any, col: any, error: any) => { this.handleError(msg); return true; }; } public handleError(error: any): void { try { // calling the injector here gave the application the time to build the correct context for the dependency injection that Http needed. if (!this.http) { this.http = this.injector.get(Http); } if (!error) { error = 'Unknown Error'; } console.error(error); this.http.post('logtoserver/LogError', { Message: error.message, StackTrace: error.stack }); } catch (exception) { // ignore } } } 

Relevant parts from CustomHttpService.ts:

 @Injectable() export class CustomHttpService extends Http { constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private router: Router, private injector: Injector) { super(backend, defaultOptions); } request(urlOrRequest: string | Request, options?: RequestOptionsArgs): Observable<Response> { // We needed Router here to call this.router.navigate(['...']); // ... } } 

app.module.ts:

 import { NgModule, ErrorHandler, Injector } from '@angular/core'; import { Http, RequestOptions, XHRBackend } from '@angular/http'; import { CustomErrorHandler } from 'app/customErrorHandler'; // ... export function customHttpServiceFactory(xhrBackend, requestOptions, router, injector) { return new CustomHttpService(xhrBackend, requestOptions, router, injector); } export function customErrorHandler(injector) { return new CustomErrorHandler(injector); } @NgModule({ declarations: [ ... ], imports: [ ... ], providers: [ { provide: Http, useFactory: customHttpServiceFactory, deps: [XHRBackend, RequestOptions, Router, Injector] }, // { provide: UrlSerializer, useClass: LowercaseUrlSerializer }, { provide: ErrorHandler, useFactory: customErrorHandler, deps: [Injector] }, ... ], bootstrap: [AppComponent] }) export class AppModule {} 
0
Oct 24 '17 at 0:03
source share



All Articles