fix(core): provide NgModuleRef in ViewContainerRef.createComponent. (#15350)

This is needed to support the corner cases:
- usage of a `ComponentFactory` that was created on the fly via `Compiler`
- overwriting of the `NgModuleRef` that is associated to a
  `ComponentFactory` by the `ComponentFactoryResolver` from
  which it was read.

Fixes #15241
This commit is contained in:
Tobias Bosch
2017-03-21 08:15:10 -07:00
committed by Miško Hevery
parent 8e6995c91e
commit 431eb309f3
6 changed files with 160 additions and 15 deletions

View File

@ -9,6 +9,7 @@
import {Injector} from '../di/injector';
import {ComponentFactory, ComponentRef} from './component_factory';
import {ElementRef} from './element_ref';
import {NgModuleRef} from './ng_module_factory';
import {TemplateRef} from './template_ref';
import {EmbeddedViewRef, ViewRef} from './view_ref';
@ -83,7 +84,7 @@ export abstract class ViewContainerRef {
*/
abstract createComponent<C>(
componentFactory: ComponentFactory<C>, index?: number, injector?: Injector,
projectableNodes?: any[][]): ComponentRef<C>;
projectableNodes?: any[][], ngModule?: NgModuleRef<any>): ComponentRef<C>;
/**
* Inserts a View identified by a {@link ViewRef} into the container at the specified `index`.

View File

@ -356,7 +356,7 @@ export function resolveDep(
}
const tokenKey = depDef.tokenKey;
if (depDef.flags & DepFlags.SkipSelf) {
if (elDef && (depDef.flags & DepFlags.SkipSelf)) {
allowPrivateServices = false;
elDef = elDef.parent;
}

View File

@ -10,6 +10,7 @@ import {ApplicationRef} from '../application_ref';
import {ChangeDetectorRef} from '../change_detection/change_detection';
import {Injector} from '../di';
import {ComponentFactory, ComponentRef} from '../linker/component_factory';
import {ComponentFactoryBoundToModule} from '../linker/component_factory_resolver';
import {ElementRef} from '../linker/element_ref';
import {NgModuleRef} from '../linker/ng_module_factory';
import {TemplateRef} from '../linker/template_ref';
@ -137,7 +138,7 @@ class ViewContainerRef_ implements ViewContainerData {
view = view.parent;
}
return view ? new Injector_(view, elDef) : this._view.root.injector;
return view ? new Injector_(view, elDef) : new Injector_(this._view, null);
}
clear(): void {
@ -169,9 +170,13 @@ class ViewContainerRef_ implements ViewContainerData {
createComponent<C>(
componentFactory: ComponentFactory<C>, index?: number, injector?: Injector,
projectableNodes?: any[][]): ComponentRef<C> {
projectableNodes?: any[][], ngModuleRef?: NgModuleRef<any>): ComponentRef<C> {
const contextInjector = injector || this.parentInjector;
const componentRef = componentFactory.create(contextInjector, projectableNodes);
if (!ngModuleRef && !(componentFactory instanceof ComponentFactoryBoundToModule)) {
ngModuleRef = contextInjector.get(NgModuleRef);
}
const componentRef =
componentFactory.create(contextInjector, projectableNodes, undefined, ngModuleRef);
this.insert(componentRef.hostView, index);
return componentRef;
}
@ -298,9 +303,10 @@ export function createInjector(view: ViewData, elDef: NodeDef): Injector {
}
class Injector_ implements Injector {
constructor(private view: ViewData, private elDef: NodeDef) {}
constructor(private view: ViewData, private elDef: NodeDef|null) {}
get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND): any {
const allowPrivateServices = (this.elDef.flags & NodeFlags.ComponentView) !== 0;
const allowPrivateServices =
this.elDef ? (this.elDef.flags & NodeFlags.ComponentView) !== 0 : false;
return Services.resolveDep(
this.view, this.elDef, allowPrivateServices,
{flags: DepFlags.None, token, tokenKey: tokenKey(token)}, notFoundValue);