Skip to content
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

Merged
merged 1 commit into from
Mar 14, 2017
Merged

Conversation

vicb
Copy link
Contributor

@vicb vicb commented Mar 9, 2017

TODO:

  • add refs to issues in commit message,
  • describe API change in commit message
  • link design doc
  • test for ViewContainerRef.parentInjector

@vicb vicb force-pushed the 0306-testinj branch 4 times, most recently from ec67a6a to 9358917 Compare March 9, 2017 22:11
if (this.ngComponentOutletNgModuleFactory) {
this._moduleRef = this.ngComponentOutletNgModuleFactory.create(injector);
const ngModuleRef = elInjector.get(NgModuleRef);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parentModule

Copy link
Contributor Author

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);
Copy link
Contributor Author

@vicb vicb Mar 9, 2017

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

Copy link
Contributor Author

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);
Copy link
Contributor Author

@vicb vicb Mar 9, 2017

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

Copy link
Contributor Author

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(); }
Copy link
Contributor Author

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

Copy link
Contributor Author

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> {
Copy link
Contributor Author

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);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert

Copy link
Contributor Author

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;
Copy link
Contributor Author

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));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TestBed.get() -> injector

Copy link
Contributor Author

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> {
Copy link
Contributor Author

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;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

injector -> ModuleRef only

Copy link
Contributor Author

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;
}

Copy link
Contributor Author

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);

Copy link
Contributor Author

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);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inject NgModuleRef

Copy link
Contributor Author

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],
Copy link
Contributor Author

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@vicb vicb mentioned this pull request Mar 10, 2017
@@ -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');
Copy link
Contributor

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?

Copy link
Contributor

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)...

Copy link
Contributor

@tbosch tbosch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed in person...

@vicb vicb added the action: merge The PR is ready for merge by the caretaker label Mar 10, 2017
@thaoula
Copy link

thaoula commented Mar 11, 2017

hi vicb,

Thanks for your hard work.

Do you have any idea when this will be merged into V4?

Regards,
Tarek

Copy link
Contributor

@IgorMinar IgorMinar left a 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

@vicb
Copy link
Contributor Author

vicb commented Mar 13, 2017

@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`
@thaoula
Copy link

thaoula commented Mar 14, 2017

Hi Vicb,

Awesome!!!. Do you know when that will be? Been waiting for a fix to this issue since November.

Regards,
Tarek

@chuckjaz chuckjaz merged commit 13686bb into angular:master Mar 14, 2017
rootSelectorOrNode: string|any = null): ComponentRef<any> {
injector: Injector, projectableNodes?: any[][], rootSelectorOrNode?: string|any,
ngModule?: NgModuleRef<any>): ComponentRef<any> {
if (!ngModule) {
Copy link

@al-pt-old al-pt-old Mar 17, 2017

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>,

Copy link
Contributor

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.

SamVerschueren pushed a commit to SamVerschueren/angular that referenced this pull request Mar 18, 2017
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`
sis0k0 added a commit to NativeScript/nativescript-angular that referenced this pull request Mar 20, 2017
sis0k0 added a commit to NativeScript/nativescript-angular that referenced this pull request Mar 20, 2017
smurfy pushed a commit to smurfy/angular that referenced this pull request Apr 7, 2017
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 pushed a commit to asnowwolf/angular that referenced this pull request Aug 11, 2017
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 pushed a commit to juleskremer/angular that referenced this pull request Aug 28, 2017
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 vicb deleted the 0306-testinj branch March 6, 2018 22:23
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 13, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants