7

I am using Lazy Loading strategy of subcomponents in my application. On the top level of application, I have custom HTTP provider which intercept all ajax calls.

    providers:[{
        provide: Http,
        useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, cookieService: CookieService) => new CustomHttp(backend, defaultOptions, cookieService),
        deps: [XHRBackend, RequestOptions, CookieService]
    }]

My lazy loaded modules do not affect this custom provider. Is there a way to provide it for them too? Without duplication of code in the providers property in the component.module file. Thank you!

Mikki
  • 6,751
  • 5
  • 31
  • 49
  • I guess you added the `HttpModule` to `imports: [...]` in at least one of the lazy loaded modules, right? – Günter Zöchbauer Dec 07 '16 at 16:26
  • @GünterZöchbauer, nope. From the angular2 default only CommonModule – Mikki Dec 07 '16 at 16:38
  • 1
    It should be provided automatically if lazy loaded modules don't override it (register a provider with the same key) – Günter Zöchbauer Dec 07 '16 at 16:39
  • `providers: [CookieService, {provide Http, useClass: CustomHttp}]` should do the same as the provider in your question. – Günter Zöchbauer Dec 07 '16 at 16:40
  • It includes few interceptors, and in case I provide it only once on the root level of application it does not affect lazy loaded modules. If I duplicate the code for nested module, they works fine. – Mikki Dec 12 '16 at 17:17
  • Weird. That doesn't align with my understanding of how modules work. Can you reproduce in a plunker? – Günter Zöchbauer Dec 12 '16 at 20:34
  • 1
    I am having the exact same issue. This actually worked as a expected with version 2.1.2 but I was having some webpack issues with that version so I pulled down the angular2 web pack starter kit which is currently on 2.2.1 and added my existing modules to it and started seeing this behavior. Did you find any solution? @Mikki. – Josh Dec 20 '16 at 14:54
  • @Josh, unfortunately - no, still looking – Mikki Dec 20 '16 at 15:27
  • @Josh Can you reproduce it somewhere? – yurzui Mar 02 '17 at 05:32
  • @yurzui I don't really have time to setup a plunkr, but I believe it is working as designed. I don't think child modules inherit built in providers from parent modules the same way they do with custom provider. – Josh Mar 02 '17 at 17:16
  • @yurzui For instance if I create a UserService and add it to providers array of app module, all child modules will get this instance of the UserService if they request one to be injected in a constructor, unless there is a UserService provided at a closer level than the app module, then the component gets the one that is closest. – Josh Mar 02 '17 at 17:17
  • 1
    @yurzui Same applies when overriding built in modules, like we are doing here with Http, the services in the child module don't get the overridden instance they get the original because it is available from the child module by default as they are built in providers. I think child modules only search up the tree if the provider is not already available at the current level, which would only apply to non-built in modules. Anyway solved this by creating a shared module with these providers that I then import into every other module. – Josh Mar 02 '17 at 17:17
  • @Josh I have custom http provider and it remains the same in all lazy modules – yurzui Mar 02 '17 at 17:31
  • @yurzui interesting, I wish mine would do the same. Which version of angular are you using? – Josh Mar 02 '17 at 17:41
  • It works in 2.4.7 for me and i have tried it in 4.0.0-rc.2 – yurzui Mar 02 '17 at 17:42
  • @yurzui I'm not sure how to replicate in a plunkr. I just tried it again on my local environment and same result. I have the app module with the overridden http provider, and then I have a lazy loaded portal module. and the portal module then has many lazy loaded feature modules. Is it possible the double lazy load hop is whats messing it up? When I remove my shared module, the feature modules stop getting the custom http provider even though the app module has it. – Josh Mar 02 '17 at 18:06
  • @Josh Do you import HttpModule somewhere besides AppModule? If yes, then remove it. – yurzui Mar 02 '17 at 18:11
  • @yurzui No it is only imported into the app module – Josh Mar 02 '17 at 18:16
  • @Josh https://plnkr.co/edit/lXCBKIkUIOfmEn0LWj9C?p=preview If you have some github repo to reproduce it i will try to take a look – yurzui Mar 02 '17 at 18:39
  • Thanks, repo is private but I will try to reproduce the issue in the plunkr you provided. – Josh Mar 02 '17 at 18:47

1 Answers1

3

I've fixed it with @SkipSelf(). Each lazy-loaded module has own injector, so it doesn't know anything about extended Http provider within an application level. While you're injecting Http provider in your services(in lazy-loaded modules) angular is trying to find Http provider in module's injector...and find the original one from '@angular/http'. But you need to find your extended Http provider which is 'visible' within application level. So try to add @SkipSelf() before Http in your constructor:

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

constructor(@SkipSelf() private http: Http) {
}