3

I have a class implementing ErrorHandler and is provided at root level. I have 3 modules in my app of which 2 of them can use ErrorHandler at root level but one of them should have different version of ErrorHandler.

I have tried creating two implementations of ErrorHandler, one of which is provided at root level, I have decorated second service with {providedIn: ThreePageModule}, but this doesn't seems like working as whenever there is an error ex: HttpErrorResponse the root level ErrorHandler kicks in. I have looked at the angular documentation and it says when a child Module is lazy loaded it gets the provided service. Am I missing something here??

Below is the app.module.ts

@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [
FormsModule,
BrowserModule,
HttpClientModule,
AppRoutingModule
],
providers: [
 ....other services...
{
  provide: HTTP_INTERCEPTORS,
  useClass: HttpConfigInterceptor,
  multi: true
},
{ provide: ErrorHandler, useClass: ExceptionHandlerService },
],
bootstrap: [AppComponent]
})
export class AppModule {}

AppRoutingModule.ts:

@NgModule({
imports: [
 RouterModule.forRoot(appRoutes)
],
exports: [
 RouterModule
]
})
export class AppRoutingModule { }

appRoutes.ts:

 export const appRoutes: Routes = [
   {
    path: 'one',
    loadChildren: './../one/one.module#OnePageModule'
 },
  {
      path: 'two',
      loadChildren: './../two/two.module#TwosPageModule'
  },
  {
    path: 'three',
    loadChildren: './../three/three.module#ThreePageModule'
  }
 ];

ThreeModule.ts

@NgModule({
imports: [
 ...Imports...
],
entryComponents: [
 ThreeComponent
],
providers: [DatePipe],
declarations: [
....Declarations.....
]
})
export class ClaimsPageModule { }

ThreeErrorHandlerService.ts

@Injectable({
  providedIn: ThreePageModule
})
export class ThreeErrorHandlerService implements ErrorHandler {

constructor() { }

handleError(error: Error | HttpErrorResponse): void {
  if (error instanceof HttpErrorResponse) {
   return;
  }
 }
}

What I want is to use ThreeErrorHandlerService in ThreePageModule while still using ExceptionHandlerService in rest of the two modules.

Is this the way we achieve it or am I doing it wrongly.

1 Answer 1

3

I think there is a way to achieve this.

app.tokens.ts


export function errorHandlerFactory (r: Router): AbstractErrorHandler {
  return r.url === '/foo' ? new ErrorHandlerThree('foo error!') : new ErrorHandlerOne('not foo !!')
}

export abstract class AbstractErrorHandler {
  abstract getCrtErr: () => string;
}

export class ErrorHandlerOne implements AbstractErrorHandler {
  constructor (public crtErr: string) { }

  getCrtErr () { return 'err!' }
}

export class ErrorHandlerThree implements AbstractErrorHandler {
  constructor (public crtErr: string) { }

  getCrtErr () { return 'err!' }
}

app.module.ts

@Component({
  selector: 'my-app',
  template: `
    <button [routerLink]="'foo'">foo route</button>

    <router-outlet></router-outlet>
  `,
})
class AppComponent {
  constructor (err: AbstractErrorHandler) {
    console.log(err) // not foo !!
  }
}

const routes: Routes = [
  { path: 'foo', loadChildren: () => import('./foo/foo.module').then(m => m.FooModule,) },
]

@NgModule({
  imports: [
    BrowserModule,
    RouterModule.forRoot(routes),
  ],
  declarations: [
    AppComponent
  ],
  providers: [
    { provide: AbstractErrorHandler, useFactory: errorHandlerFactory, deps: [Router] }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

foo.module.ts

@Component({
  selector: 'foo-comp',
  template: `this is foo!`,
})
export class FooComp {
  constructor (err: AbstractErrorHandler) {
    console.log('foo', err) // foo error!
  }
}

const routes: Routes = [
  { path: '', component: FooComp, }
]

@NgModule({
  declarations: [FooComp],
  imports: [
    CommonModule,
    RouterModule.forChild(routes),
  ],
  providers: [
    { provide: AbstractErrorHandler, useFactory: errorHandlerFactory, deps: [Router] }
  ],

Note that you might need to track class instances inside app.tokens.ts as you might not want a new instance every time a component injects your this dependency.

FactoryProvider.

ng-run demo.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.