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`
This commit is contained in:

committed by
Chuck Jazdzewski

parent
f093501501
commit
13686bb518
@ -8,8 +8,6 @@
|
||||
|
||||
import {ComponentFactoryResolver, ComponentRef, Directive, Injector, Input, NgModuleFactory, NgModuleRef, OnChanges, OnDestroy, Provider, SimpleChanges, Type, ViewContainerRef} from '@angular/core';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates a single {@link Component} type and inserts its Host View into current View.
|
||||
* `NgComponentOutlet` provides a declarative approach for dynamic component creation.
|
||||
@ -81,34 +79,35 @@ export class NgComponentOutlet implements OnChanges, OnDestroy {
|
||||
constructor(private _viewContainerRef: ViewContainerRef) {}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (this._componentRef) {
|
||||
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._componentRef.hostView));
|
||||
}
|
||||
this._viewContainerRef.clear();
|
||||
this._componentRef = null;
|
||||
|
||||
if (this.ngComponentOutlet) {
|
||||
let injector = this.ngComponentOutletInjector || this._viewContainerRef.parentInjector;
|
||||
const elInjector = this.ngComponentOutletInjector || this._viewContainerRef.parentInjector;
|
||||
|
||||
if ((changes as any).ngComponentOutletNgModuleFactory) {
|
||||
if (changes['ngComponentOutletNgModuleFactory']) {
|
||||
if (this._moduleRef) this._moduleRef.destroy();
|
||||
|
||||
if (this.ngComponentOutletNgModuleFactory) {
|
||||
this._moduleRef = this.ngComponentOutletNgModuleFactory.create(injector);
|
||||
const parentModule = elInjector.get(NgModuleRef);
|
||||
this._moduleRef = this.ngComponentOutletNgModuleFactory.create(parentModule.injector);
|
||||
} else {
|
||||
this._moduleRef = null;
|
||||
}
|
||||
}
|
||||
if (this._moduleRef) {
|
||||
injector = this._moduleRef.injector;
|
||||
}
|
||||
|
||||
let componentFactory =
|
||||
injector.get(ComponentFactoryResolver).resolveComponentFactory(this.ngComponentOutlet);
|
||||
const componentFactoryResolver = this._moduleRef ? this._moduleRef.componentFactoryResolver :
|
||||
elInjector.get(ComponentFactoryResolver);
|
||||
|
||||
const componentFactory =
|
||||
componentFactoryResolver.resolveComponentFactory(this.ngComponentOutlet);
|
||||
|
||||
this._componentRef = this._viewContainerRef.createComponent(
|
||||
componentFactory, this._viewContainerRef.length, injector, this.ngComponentOutletContent);
|
||||
componentFactory, this._viewContainerRef.length, elInjector,
|
||||
this.ngComponentOutletContent);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this._moduleRef) this._moduleRef.destroy();
|
||||
}
|
||||
|
@ -177,13 +177,13 @@ export function main() {
|
||||
it('should not re-create moduleRef when it didn\'t actually change', async(() => {
|
||||
const compiler = TestBed.get(Compiler) as Compiler;
|
||||
const fixture = TestBed.createComponent(TestComponent);
|
||||
|
||||
fixture.componentInstance.module = compiler.compileModuleSync(TestModule2);
|
||||
fixture.componentInstance.currentComponent = Module2InjectedComponent;
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.nativeElement).toHaveText('baz');
|
||||
|
||||
const moduleRef = fixture.componentInstance.ngComponentOutlet['_moduleRef'];
|
||||
|
||||
fixture.componentInstance.currentComponent = Module2InjectedComponent2;
|
||||
fixture.detectChanges();
|
||||
|
||||
@ -247,11 +247,11 @@ class TestComponent {
|
||||
export class TestModule {
|
||||
}
|
||||
|
||||
@Component({selector: 'mdoule-2-injected-component', template: 'baz'})
|
||||
@Component({selector: 'module-2-injected-component', template: 'baz'})
|
||||
class Module2InjectedComponent {
|
||||
}
|
||||
|
||||
@Component({selector: 'mdoule-2-injected-component-2', template: 'baz2'})
|
||||
@Component({selector: 'module-2-injected-component-2', template: 'baz2'})
|
||||
class Module2InjectedComponent2 {
|
||||
}
|
||||
|
||||
@ -264,7 +264,7 @@ class Module2InjectedComponent2 {
|
||||
export class TestModule2 {
|
||||
}
|
||||
|
||||
@Component({selector: 'mdoule-3-injected-component', template: 'bat'})
|
||||
@Component({selector: 'module-3-injected-component', template: 'bat'})
|
||||
class Module3InjectedComponent {
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user