feat(upgrade): support lazy-loading Angular module into AngularJS app

This commit is contained in:
Georgios Kalpakas
2017-07-11 16:15:51 +03:00
committed by Alex Rickabaugh
parent 44b50427d9
commit 30e76fcd80
12 changed files with 431 additions and 37 deletions

View File

@ -9,9 +9,14 @@
import {ComponentFactory, ComponentFactoryResolver, Injector, Type} from '@angular/core';
import * as angular from './angular1';
import {$COMPILE, $INJECTOR, $PARSE, INJECTOR_KEY, REQUIRE_INJECTOR, REQUIRE_NG_MODEL} from './constants';
import {$COMPILE, $INJECTOR, $PARSE, INJECTOR_KEY, LAZY_MODULE_REF, REQUIRE_INJECTOR, REQUIRE_NG_MODEL} from './constants';
import {DowngradeComponentAdapter} from './downgrade_component_adapter';
import {controllerKey, getComponentName} from './util';
import {LazyModuleRef, controllerKey, getComponentName, isFunction} from './util';
interface Thenable<T> {
then(callback: (value: T) => any): any;
}
let downgradeCount = 0;
@ -50,6 +55,8 @@ let downgradeCount = 0;
*/
export function downgradeComponent(info: {
component: Type<any>;
/** @experimental */
propagateDigest?: boolean;
/** @deprecated since v4. This parameter is no longer used */
inputs?: string[];
/** @deprecated since v4. This parameter is no longer used */
@ -76,9 +83,14 @@ export function downgradeComponent(info: {
// triggered by `UpgradeNg1ComponentAdapterBuilder`, before the Angular templates have
// been compiled.
const parentInjector: Injector|ParentInjectorPromise =
required[0] || $injector.get(INJECTOR_KEY);
const ngModel: angular.INgModelController = required[1];
let parentInjector: Injector|Thenable<Injector>|undefined = required[0];
let ranAsync = false;
if (!parentInjector) {
const lazyModuleRef = $injector.get(LAZY_MODULE_REF) as LazyModuleRef;
parentInjector = lazyModuleRef.injector || lazyModuleRef.promise;
}
const downgradeFn = (injector: Injector) => {
const componentFactoryResolver: ComponentFactoryResolver =
@ -98,18 +110,26 @@ export function downgradeComponent(info: {
const projectableNodes = facade.compileContents();
facade.createComponent(projectableNodes);
facade.setupInputs();
facade.setupInputs(info.propagateDigest);
facade.setupOutputs();
facade.registerCleanup();
injectorPromise.resolve(facade.getInjector());
if (ranAsync) {
// If this is run async, it is possible that it is not run inside a
// digest and initial input values will not be detected.
scope.$evalAsync(() => {});
}
};
if (parentInjector instanceof ParentInjectorPromise) {
if (isThenable<Injector>(parentInjector)) {
parentInjector.then(downgradeFn);
} else {
downgradeFn(parentInjector);
}
ranAsync = true;
}
};
};
@ -155,3 +175,7 @@ class ParentInjectorPromise {
this.callbacks.length = 0;
}
}
function isThenable<T>(obj: object): obj is Thenable<T> {
return isFunction((obj as any).then);
}