-
Notifications
You must be signed in to change notification settings - Fork 25.5k
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
fix: element injector vs module injector #15044
Conversation
ec67a6a
to
9358917
Compare
if (this.ngComponentOutletNgModuleFactory) { | ||
this._moduleRef = this.ngComponentOutletNgModuleFactory.create(injector); | ||
const ngModuleRef = elInjector.get(NgModuleRef); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parentModule
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
result = this._parent.resolveComponentFactory(component); | ||
} | ||
return result; | ||
let factory = this._factories.get(component) || this._parent.resolveComponentFactory(component); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add tests
override provider in a child module
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -502,7 +501,7 @@ export class ApplicationRef_ extends ApplicationRef { | |||
componentFactory = this._componentFactoryResolver.resolveComponentFactory(componentOrFactory); | |||
} | |||
this._rootComponentTypes.push(componentFactory.componentType); | |||
const compRef = componentFactory.create(this._injector, [], componentFactory.selector); | |||
const compRef = componentFactory.create(Injector.NULL, [], componentFactory.selector); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test:
-
create a child module and bootstrap a cmp from it, should see child providers.
-
only pass a module if component factory has no
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
} | ||
|
||
export class ComponentFactoryBoundToModule<C> extends ComponentFactory<C> { | ||
constructor(private factory: ComponentFactory<C>, private ngModule: NgModuleRef<any>) { super(); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ngModule should be public on ComponentFactory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not for now
injector: Injector, projectableNodes: any[][] = null, | ||
rootSelectorOrNode: string|any = null): ComponentRef<any> { | ||
injector: Injector, projectableNodes?: any[][], rootSelectorOrNode?: string|any, | ||
ngModule?: NgModuleRef<any>): ComponentRef<any> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw if no ngModule
const viewDef = resolveViewDefinition(this.viewDefFactory); | ||
const componentNodeIndex = viewDef.nodes[0].element.componentProvider.index; | ||
const module = ngModule || injector.get(NgModuleRef); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revert
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -105,7 +107,8 @@ class ViewContainerRef_ implements ViewContainerRef { | |||
elDef = viewParentEl(view); | |||
view = view.parent; | |||
} | |||
return view ? new Injector_(view, elDef) : this._view.root.injector; | |||
|
|||
return view ? new Injector_(view, elDef) : Injector.NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revert
add test: inject ViewContainerRef
on a cmp TestBed.create(Comp).get()
@@ -130,9 +130,13 @@ function declareTests({useJit}: {useJit: boolean}) { | |||
} | |||
|
|||
function createComp<T>(compType: Type<T>, moduleType: Type<any>): ComponentFixture<T> { | |||
const ngModule = createModule(moduleType); | |||
const ngModule = createModule(moduleType, TestBed.get(Injector)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TestBed.get() -> injector
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -280,7 +282,9 @@ class ApplyRedirects { | |||
|
|||
private getChildConfig(injector: Injector, route: Route): Observable<LoadedRouterConfig> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check if we can pass the module instead
@@ -991,7 +991,7 @@ export class PreActivation { | |||
|
|||
private getToken(token: any, snapshot: ActivatedRouteSnapshot): any { | |||
const config = closestLoadedConfig(snapshot); | |||
const injector = config ? config.injector : this.injector; | |||
const injector = config ? config.module.injector : this.injector; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
injector -> ModuleRef only
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no -> API break
} else { | ||
injector = outlet.locationInjector; | ||
resolver = outlet.locationFactoryResolver; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add simpler method & deprecate
outlet.activate(future, resolver, outletMap);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -91,37 +91,40 @@ export class RouterPreloader { | |||
this.subscription = concatMap.call(navigations, () => this.preload()).subscribe(() => {}); | |||
} | |||
|
|||
preload(): Observable<any> { return this.processRoutes(this.injector, this.router.config); } | |||
preload(): Observable<any> { | |||
const ngModule = this.injector.get(NgModuleRef); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inject NgModuleRef
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, API break
@@ -2422,6 +2422,175 @@ describe('Integration', () => { | |||
expect(fixture.nativeElement).toHaveText('lazy-loaded-parent [lazy-loaded-child]'); | |||
}))); | |||
|
|||
it('should have 2 injector trees: module and element', | |||
fakeAsync(inject( | |||
[Router, Location, NgModuleFactoryLoader], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add module can no longer shadow el
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -55,11 +55,13 @@ class ComponentFactory_ extends ComponentFactory<any> { | |||
create( | |||
injector: Injector, projectableNodes?: any[][], rootSelectorOrNode?: string|any, | |||
ngModule?: NgModuleRef<any>): ComponentRef<any> { | |||
if (!ngModule) { | |||
throw new Error('ngModule should be provided'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe Illegal sate: NgModule has to be provided
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(as its an error that users never should run into)...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed in person...
hi vicb, Thanks for your hard work. Do you have any idea when this will be merged into V4? Regards, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm for api changes
@thaoula should be part of the next RC release |
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`
Hi Vicb, Awesome!!!. Do you know when that will be? Been waiting for a fix to this issue since November. Regards, |
rootSelectorOrNode: string|any = null): ComponentRef<any> { | ||
injector: Injector, projectableNodes?: any[][], rootSelectorOrNode?: string|any, | ||
ngModule?: NgModuleRef<any>): ComponentRef<any> { | ||
if (!ngModule) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hi!
ngModule is defined as an optional variable, but here we see throw instruction.
Why?
After upgrading to 4.0.rc-4 we got an Exception below
ngModule should be provided
export declare abstract class ViewContainerRef {
abstract createComponent<C>(componentFactory: ComponentFactory<C>,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class implements the ComponentFactory<any>
which requires this parameter be optional (https://github.com/angular/angular/blob/4.0.0-rc.4/packages/core/src/linker/component_factory.ts#L76-L78). However, this is an internal implementation that should never be called without a module so we check for internal consistency.
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`
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`
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`
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`
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
TODO:
ViewContainerRef.parentInjector