New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DI: Resolve Guard and Component both create a service which is 'provided' in a lazy loaded module #13870

Closed
jeanpaulattard opened this Issue Jan 11, 2017 · 6 comments

Comments

Projects
None yet
7 participants
@jeanpaulattard

jeanpaulattard commented Jan 11, 2017

I'm submitting a ... (check one with "x")

[x ] bug report => search github for a similar issue or PR before submitting

I've encountered an issue where a resolve route-guard did not share the same service with a component that is registered to the same module the Resolve guard is.

I have a scenario where the resolve guard of a route bound to a lazy loaded module retrieves a list of data from the backend and caches it on a variable within the service. The same service has another method (that is called from a component) which retrieves fine grained data, first by looking within the cached data, and if not found retrievs that particular subset of data from backend. The issue is that the the Service is recreated when the component is visited as well, thus losing the cached data.

I've been boggling my mind around this issue and I cannot seem to make sense of what is happening. I've read the docs on dependency injection, hierarchical injection and modules. From my understanding the application has a root injector which is bound to the AppModule that is bootstrapped. Child injectors are created for each component, and for each lazy loaded module. Whenever a Service is needed, first the service is looked within the injector bound to the Component, and if not found, checkes in the parent component, and continues going up through the injector tree until reaching the module injector (and if not found here throws an error).

Now if the Service I needed is 'provided' within the lazy loaded module, shouldn't the Resolve guard and the component share the same Singleton Service bound to the module injector? I'm reporting this as a bug because 1) the docs does imply that, and 2) this problem seems to be occuring only with injectors of lazy loaded modules, and not the root module. See the following plunker.

https://plnkr.co/edit/G6I7m8duZMOCFdnuuk3l?p=preview

When a service bound to the root module is used by both the Resolve guard and the Component, the service is shared... However when the same logic is applied to the lazy loaded module, the service is created and recreated both when the Resolve Guard is instantiated and when the Component is instantiated respectively. The plunker above demos it. The logic for the retrieval of data in the root module and lazy loaded module is the same (different services/components ofcourse), however the creation of the service behave differently.

Expected behavior
Only one instance of the Service 'provided' in the lazy loaded module should be created when accessed via the resolve guard, and a second creation (which overrides the first creation) SHOULD NOT take place when the Component is accessed.

Minimal reproduction of the problem with instructions

https://plnkr.co/edit/G6I7m8duZMOCFdnuuk3l?p=preview

Please tell us about your environment:

Operating system: windows 10
IDE: Webstorm
Package manager: NPM
HTTP server: Webpack dev server

  • Angular version: 2.4.2

  • Language: Typescript 2.0.10

@DzmitryShylovich

This comment has been minimized.

Contributor

DzmitryShylovich commented Jan 11, 2017

Yeah, it's a known issue. See #12869

@jeanpaulattard

This comment has been minimized.

jeanpaulattard commented Jan 11, 2017

Hi @DzmitryShylovich , thanks for getting my attention to it.

@matsko matsko added the comp: router label Jan 11, 2017

@guidoffm

This comment has been minimized.

guidoffm commented Jan 13, 2017

I have the same problem. I want to initialize some things in services. I have set a CanActivate guard for the root component of the lazy loaded feature module. The guard should initialize all the services before starting the feature module. This works. But then, when I access a service from a component the service is created again. Maybe someone has work around for this.

@rhessus

This comment has been minimized.

rhessus commented Jan 15, 2017

I have the same problem :(

@readren

This comment has been minimized.

readren commented Jan 19, 2017

Mee too. A work around is downgrading the router to version 3.1.x.
I'm using router version 3.1.1 with core version 2.4.2 with no apparent issues other than unmet peer dependency messages.

@DzmitryShylovich

This comment has been minimized.

Contributor

DzmitryShylovich commented Feb 1, 2017

vicb added a commit to vicb/angular that referenced this issue Mar 10, 2017

fix: element injector vs module injector
fixes angular#12869
fixes angular#12889
fixes angular#13885
fixes angular#13870

Before this change there was a single injector tree.
Now we have 2 injector trees, one for the modules and one for the components.
This fixes lazy loading modules.

See the design docs for details:
https://docs.google.com/document/d/1OEUIwc-s69l1o97K0wBd_-Lth5BBxir1KuCRWklTlI4

BREAKING CHANGES

`ComponentFactory.create()` takes an extra optional `NgModuleRef` parameter.
No change should be required in user code as the correct module will be used
when none is provided

DEPRECATIONS

The following methods were used internally and are no more required:
- `RouterOutlet.locationFactoryResolver`
- `RouterOutlet.locationInjector`

vicb added a commit to vicb/angular that referenced this issue Mar 10, 2017

fix: element injector vs module injector
fixes angular#12869
fixes angular#12889
fixes angular#13885
fixes angular#13870

Before this change there was a single injector tree.
Now we have 2 injector trees, one for the modules and one for the components.
This fixes lazy loading modules.

See the design docs for details:
https://docs.google.com/document/d/1OEUIwc-s69l1o97K0wBd_-Lth5BBxir1KuCRWklTlI4

BREAKING CHANGES

`ComponentFactory.create()` takes an extra optional `NgModuleRef` parameter.
No change should be required in user code as the correct module will be used
when none is provided

DEPRECATIONS

The following methods were used internally and are no more required:
- `RouterOutlet.locationFactoryResolver`
- `RouterOutlet.locationInjector`

vicb added a commit to vicb/angular that referenced this issue Mar 10, 2017

fix: element injector vs module injector
fixes angular#12869
fixes angular#12889
fixes angular#13885
fixes angular#13870

Before this change there was a single injector tree.
Now we have 2 injector trees, one for the modules and one for the components.
This fixes lazy loading modules.

See the design docs for details:
https://docs.google.com/document/d/1OEUIwc-s69l1o97K0wBd_-Lth5BBxir1KuCRWklTlI4

BREAKING CHANGES

`ComponentFactory.create()` takes an extra optional `NgModuleRef` parameter.
No change should be required in user code as the correct module will be used
when none is provided

DEPRECATIONS

The following methods were used internally and are no more required:
- `RouterOutlet.locationFactoryResolver`
- `RouterOutlet.locationInjector`

vicb added a commit to vicb/angular that referenced this issue Mar 13, 2017

fix: element injector vs module injector
fixes angular#12869
fixes angular#12889
fixes angular#13885
fixes angular#13870

Before this change there was a single injector tree.
Now we have 2 injector trees, one for the modules and one for the components.
This fixes lazy loading modules.

See the design docs for details:
https://docs.google.com/document/d/1OEUIwc-s69l1o97K0wBd_-Lth5BBxir1KuCRWklTlI4

BREAKING CHANGES

`ComponentFactory.create()` takes an extra optional `NgModuleRef` parameter.
No change should be required in user code as the correct module will be used
when none is provided

DEPRECATIONS

The following methods were used internally and are no more required:
- `RouterOutlet.locationFactoryResolver`
- `RouterOutlet.locationInjector`

chuckjaz added a commit that referenced this issue Mar 14, 2017

fix: element injector vs module injector (#15044)
fixes #12869
fixes #12889
fixes #13885
fixes #13870

Before this change there was a single injector tree.
Now we have 2 injector trees, one for the modules and one for the components.
This fixes lazy loading modules.

See the design docs for details:
https://docs.google.com/document/d/1OEUIwc-s69l1o97K0wBd_-Lth5BBxir1KuCRWklTlI4

BREAKING CHANGES

`ComponentFactory.create()` takes an extra optional `NgModuleRef` parameter.
No change should be required in user code as the correct module will be used
when none is provided

DEPRECATIONS

The following methods were used internally and are no more required:
- `RouterOutlet.locationFactoryResolver`
- `RouterOutlet.locationInjector`

SamVerschueren added a commit to SamVerschueren/angular that referenced this issue Mar 18, 2017

fix: element injector vs module injector (angular#15044)
fixes angular#12869
fixes angular#12889
fixes angular#13885
fixes angular#13870

Before this change there was a single injector tree.
Now we have 2 injector trees, one for the modules and one for the components.
This fixes lazy loading modules.

See the design docs for details:
https://docs.google.com/document/d/1OEUIwc-s69l1o97K0wBd_-Lth5BBxir1KuCRWklTlI4

BREAKING CHANGES

`ComponentFactory.create()` takes an extra optional `NgModuleRef` parameter.
No change should be required in user code as the correct module will be used
when none is provided

DEPRECATIONS

The following methods were used internally and are no more required:
- `RouterOutlet.locationFactoryResolver`
- `RouterOutlet.locationInjector`

smurfy pushed a commit to smurfy/angular that referenced this issue Apr 7, 2017

fix: element injector vs module injector (angular#15044)
fixes angular#12869
fixes angular#12889
fixes angular#13885
fixes angular#13870

Before this change there was a single injector tree.
Now we have 2 injector trees, one for the modules and one for the components.
This fixes lazy loading modules.

See the design docs for details:
https://docs.google.com/document/d/1OEUIwc-s69l1o97K0wBd_-Lth5BBxir1KuCRWklTlI4

BREAKING CHANGES

`ComponentFactory.create()` takes an extra optional `NgModuleRef` parameter.
No change should be required in user code as the correct module will be used
when none is provided

DEPRECATIONS

The following methods were used internally and are no more required:
- `RouterOutlet.locationFactoryResolver`
- `RouterOutlet.locationInjector`

asnowwolf added a commit to asnowwolf/angular that referenced this issue Aug 11, 2017

fix: element injector vs module injector (angular#15044)
fixes angular#12869
fixes angular#12889
fixes angular#13885
fixes angular#13870

Before this change there was a single injector tree.
Now we have 2 injector trees, one for the modules and one for the components.
This fixes lazy loading modules.

See the design docs for details:
https://docs.google.com/document/d/1OEUIwc-s69l1o97K0wBd_-Lth5BBxir1KuCRWklTlI4

BREAKING CHANGES

`ComponentFactory.create()` takes an extra optional `NgModuleRef` parameter.
No change should be required in user code as the correct module will be used
when none is provided

DEPRECATIONS

The following methods were used internally and are no more required:
- `RouterOutlet.locationFactoryResolver`
- `RouterOutlet.locationInjector`

juleskremer added a commit to juleskremer/angular that referenced this issue Aug 28, 2017

fix: element injector vs module injector (angular#15044)
fixes angular#12869
fixes angular#12889
fixes angular#13885
fixes angular#13870

Before this change there was a single injector tree.
Now we have 2 injector trees, one for the modules and one for the components.
This fixes lazy loading modules.

See the design docs for details:
https://docs.google.com/document/d/1OEUIwc-s69l1o97K0wBd_-Lth5BBxir1KuCRWklTlI4

BREAKING CHANGES

`ComponentFactory.create()` takes an extra optional `NgModuleRef` parameter.
No change should be required in user code as the correct module will be used
when none is provided

DEPRECATIONS

The following methods were used internally and are no more required:
- `RouterOutlet.locationFactoryResolver`
- `RouterOutlet.locationInjector`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment