title: Angular 4.3 Interceptors for Lazy Loaded Modules
body: <p>What is the best practice to use core module service in lazy loaded feature module and  feature child modules.<br>
  As per Angular style guide I have the following </p>
  
  <pre><code> app
     -core
         - core.module.ts
         -logger.service.ts
         -token-interceptor.service.ts
         -authentication.service.ts
     -shared
         -shared.module.ts
     -base module (my feature base , lazy loaded with router-outlet)
       -base.module.ts
       -base.routing.module.ts
       -base
         -base.component.ts
       -admin (lazy loaded , child module of base module)
        -admin.module.ts
        -admin.routing.ts
        -admin-component.ts 
       -report(lazy loaded , child module of base module, sibling of admin)
        -report.module.ts
        -report.routing.ts
        -report-component.ts
  </code></pre>
  
  <p>If I add TokenInterceptorService as a provider in all feature module,then HTTP interceptor works.
  When I add it in App module,(but not in lazy loaded feature module) it does not intercept http request triggered in lazy loaded feature module.</p>
  
  <p>What is the best practice,  of using services/interceptor   declared in core module.</p>
  
  <p>app.module.ts</p>
  
  <pre><code>@NgModule({
    declarations: [
      AppComponent,
      LoginComponent,
    ],
    imports: [
      BrowserModule,BrowserAnimationsModule, CoreModule, AppRoutingModule, FormsModule
    ], providers: [{ provide: HTTP_INTERCEPTORS, useClass: TokenInterceptorService, multi: true }],
    bootstrap: [AppComponent]
  })
  export class AppModule { }
  </code></pre>
  
  <p>app-routing.module.ts</p>
  
  <pre><code>@NgModule({
      imports: [
          RouterModule.forRoot([
              { path: 'login', component: LoginComponent },
              { path: '', redirectTo: 'base', pathMatch: 'full' },                   
              {  path: 'base', loadChildren: 'app/base/base.module#BaseModule'  }            
          ])
      ],
      exports: [
          RouterModule
      ]
  })
  export class AppRoutingModule {
  }
  </code></pre>
  
  <p>core.module.ts</p>
  
  <pre><code>@NgModule({
    imports: [
      CommonModule, HttpModule,  
    ],
    declarations: [],
    providers: [LoggerService, AuthenticationService]
  })
  export class CoreModule {
    constructor( @Optional() @SkipSelf() parentModule: CoreModule) {
      throwIfAlreadyLoaded(parentModule, 'CoreModule');
    }
  }
  </code></pre>
  
  <p>token-interceptor.service.ts</p>
  
  <pre><code>import { Injectable } from '@angular/core';
      import { Router } from '@angular/router';
      import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpErrorResponse } from '@angular/common/http';
      import { Observable } from 'rxjs/Observable';
      import 'rxjs/add/operator/do';
  
      import { AuthenticationService } from './authentication.service';
  
      @Injectable()
      export class TokenInterceptorService implements HttpInterceptor {
  
  
        constructor(public auth: AuthenticationService, private router: Router) { }
  
        intercept(request: HttpRequest&lt;any&gt;, next: HttpHandler): Observable&lt;HttpEvent&lt;any&gt;&gt; {
          console.log('Adding authorization header')
  
          request = request.clone({
            setHeaders: { authorization: this.auth.getToken() }
          });
          console.log('Added authorization header')
          return next.handle(request).do(event =&gt; { }, (err: HttpErrorResponse) =&gt; {
            console.log("Error ===&gt;", err);
            if (err.error instanceof Error) {
              // A client-side or network error occurred. Handle it accordingly.
              console.log('An error occurred:', err.error.message);
            } else if (err.status == 401) {
  
              console.log('Status 401  unautorized');
              this.router.navigate(['/login']);
            } else {
              // The backend returned an unsuccessful response code.
              // The response body may contain clues as to what went wrong,
              console.log(`Backend returned code ${err.status}, body was: ${err.error}`);
            }
  
            return Observable.throw(new Error('Your custom error'));
          });;
        }
  
      }
  </code></pre>
  
  <p>base.module.ts  </p>
  
  <pre><code> @NgModule({
        imports: [
          CommonModule, BaseRoutingModule
        ],
        declarations: [BaseComponent],
        providers: [],
      })
      export class BaseModule {
  
  
        constructor( @Optional() @SkipSelf() parentModule: BaseModule) {
  
          if (parentModule) {
            throw new Error(
              'BaseModule is already loaded. Import it in the AppModule only');
          }
        }
      }
  </code></pre>
  
  <p>base.routing.module.ts</p>
  
  <pre><code>@NgModule({
      imports: [
          RouterModule.forChild([
              {
                  path: '', component: BaseComponent,
                  children: [
  
                      { path: '', redirectTo: 'admin', pathMatch: 'full' },
                      { path: 'admin', loadChildren: 'app/base/admin/admin.module#AdminModule' },                         
                  ]
              }])
      ],
      exports: [
          RouterModule
      ]
  })
  export class BaseRoutingModule {
  }
  </code></pre>
  
  <p>admin.module.ts</p>
  
  <pre><code>@NgModule({
    imports: [
      CommonModule, FormsModule, HttpClientModule, AdminRoutingModule,BusyModule
    ],
    declarations: [UserListComponent, UserComponent, MenuListComponent, MenuComponent, CodeListComponent, CodeComponent],
    providers: [CodeService, UserService, MenuService,{ provide: HTTP_INTERCEPTORS, useClass: TokenInterceptorService, multi: true }]
  })
  export class AdminModule { }
  </code></pre>
  
  <p>admin.routing.module.ts</p>
  
  <pre><code>@NgModule({
      imports: [
          RouterModule.forChild([
  
              {
                  path: '',
                  children: [
                      { path: '', redirectTo:'code-list', pathMatch: 'full'  },
                      { path: 'code-list', component: CodeListComponent },
                      { path: 'code/:id', component: CodeComponent },
  
                      { path: 'user-list', component: UserListComponent },
                      { path: 'user/:id', component: UserComponent },
  
                      { path: 'menu-list', component: MenuListComponent },
                      { path: 'menu/:id', component: MenuComponent },                    
                  ]
              }
          ])
      ],
      exports: [
          RouterModule
      ]
  })
  export class AdminRoutingModule {
  }
  </code></pre>