diff --git a/src/directives/uiView.ts b/src/directives/uiView.ts index 724978c7..a9a54ebb 100755 --- a/src/directives/uiView.ts +++ b/src/directives/uiView.ts @@ -1,13 +1,13 @@ import { Component, - ComponentFactory, - ComponentFactoryResolver, + ComponentMirror, ComponentRef, Inject, Injector, Input, OnDestroy, OnInit, + reflectComponentType, ViewChild, ViewContainerRef, } from '@angular/core'; @@ -32,7 +32,6 @@ import { ViewContext, } from '@uirouter/core'; import { Ng2ViewConfig } from '../statebuilders/views'; -import { MergeInjector } from '../mergeInjector'; /** @hidden */ let id = 0; @@ -57,7 +56,7 @@ interface InputMapping { * * @internal */ -const ng2ComponentInputs = (factory: ComponentFactory): InputMapping[] => { +const ng2ComponentInputs = (factory: ComponentMirror): InputMapping[] => { return factory.inputs.map((input) => ({ prop: input.propName, token: input.templateName })); }; @@ -290,12 +289,20 @@ export class UIView implements OnInit, OnDestroy { const componentClass = config.viewDecl.component; // Create the component - const compFactoryResolver = componentInjector.get(ComponentFactoryResolver); - const compFactory = compFactoryResolver.resolveComponentFactory(componentClass); - this._componentRef = this._componentTarget.createComponent(compFactory, undefined, componentInjector); + const moduleInjector = context.getResolvable(NATIVE_INJECTOR_TOKEN).data; + + this._componentRef = this._componentTarget.createComponent(componentClass, { + injector: componentInjector, + environmentInjector: moduleInjector + }); // Wire resolves to @Input()s - this._applyInputBindings(compFactory, this._componentRef.instance, context, componentClass); + this._applyInputBindings( + reflectComponentType(componentClass), + this._componentRef.instance, + context, + componentClass + ); } /** @@ -321,10 +328,8 @@ export class UIView implements OnInit, OnDestroy { newProviders.push({ provide: UIView.PARENT_INJECT, useValue: parentInject }); const parentComponentInjector = this.viewContainerRef.injector; - const moduleInjector = context.getResolvable(NATIVE_INJECTOR_TOKEN).data; - const mergedParentInjector = new MergeInjector(moduleInjector, parentComponentInjector); - return Injector.create(newProviders, mergedParentInjector); + return Injector.create({ providers: newProviders, parent: parentComponentInjector }); } /** @@ -333,7 +338,7 @@ export class UIView implements OnInit, OnDestroy { * Finds component inputs which match resolves (by name) and sets the input value * to the resolve data. */ - private _applyInputBindings(factory: ComponentFactory, component: any, context: ResolveContext, componentClass) { + private _applyInputBindings(factory: ComponentMirror, component: any, context: ResolveContext, componentClass) { const bindings = this._uiViewData.config.viewDecl['bindings'] || {}; const explicitBoundProps = Object.keys(bindings); diff --git a/src/lazyLoad/lazyLoadNgModule.ts b/src/lazyLoad/lazyLoadNgModule.ts index e4d362ac..b25f7580 100644 --- a/src/lazyLoad/lazyLoadNgModule.ts +++ b/src/lazyLoad/lazyLoadNgModule.ts @@ -1,11 +1,10 @@ -import { NgModuleRef, Injector, NgModuleFactory, Type, Compiler } from '@angular/core'; +import { NgModuleRef, Injector, Type, createNgModule } from '@angular/core'; import { Transition, LazyLoadResult, UIRouter, Resolvable, NATIVE_INJECTOR_TOKEN, - isString, unnestR, inArray, StateObject, @@ -72,42 +71,16 @@ export function loadNgModule( ): (transition: Transition, stateObject: StateDeclaration) => Promise { return (transition: Transition, stateObject: StateDeclaration) => { const ng2Injector = transition.injector().get(NATIVE_INJECTOR_TOKEN); - - const createModule = (factory: NgModuleFactory) => factory.create(ng2Injector); - + const unwrapEsModuleDefault = x => (x && x.__esModule && x['default'] ? x['default'] : x); const applyModule = (moduleRef: NgModuleRef) => applyNgModule(transition, moduleRef, ng2Injector, stateObject); - return loadModuleFactory(moduleToLoad, ng2Injector).then(createModule).then(applyModule); + return Promise.resolve(moduleToLoad()) + .then(unwrapEsModuleDefault) + .then((ngModule: Type) => createNgModule(ngModule, ng2Injector)) + .then(applyModule); }; } -/** - * Returns the module factory that can be used to instantiate a module - * - * For a Type or Promise> this: - * - Compiles the component type (if not running with AOT) - * - Returns the NgModuleFactory resulting from compilation (or direct loading if using AOT) as a Promise - * - * @internal - */ -export function loadModuleFactory( - moduleToLoad: ModuleTypeCallback, - ng2Injector: Injector -): Promise> { - const compiler: Compiler = ng2Injector.get(Compiler); - - const unwrapEsModuleDefault = (x) => (x && x.__esModule && x['default'] ? x['default'] : x); - - return Promise.resolve(moduleToLoad()) - .then(unwrapEsModuleDefault) - .then((t: NgModuleFactory | Type) => { - if (t instanceof NgModuleFactory) { - return t; - } - return compiler.compileModuleAsync(t); - }); -} - /** * Apply the UI-Router Modules found in the lazy loaded module. * diff --git a/src/mergeInjector.ts b/src/mergeInjector.ts deleted file mode 100644 index b82a45a9..00000000 --- a/src/mergeInjector.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Injector } from '@angular/core'; - -/** - * Merge two injectors - * - * This class implements the Injector ng2 interface but delegates - * to the Injectors provided in the constructor. - */ -export class MergeInjector implements Injector { - static NOT_FOUND = {}; - private injectors: Injector[]; - constructor(...injectors: Injector[]) { - if (injectors.length < 2) throw new Error('pass at least two injectors'); - this.injectors = injectors; - } - - /** - * Get the token from the first injector which contains it. - * - * Delegates to the first Injector.get(). - * If not found, then delegates to the second Injector (and so forth). - * If no Injector contains the token, return the `notFoundValue`, or throw. - * - * @param token the DI token - * @param notFoundValue the value to return if none of the Injectors contains the token. - * @returns {any} the DI value - */ - get(token: any, notFoundValue?: any): any { - for (let i = 0; i < this.injectors.length; i++) { - const val = this.injectors[i].get(token, MergeInjector.NOT_FOUND); - if (val !== MergeInjector.NOT_FOUND) return val; - } - - if (arguments.length >= 2) return notFoundValue; - - // This will throw the DI Injector error - this.injectors[0].get(token); - } -}