fix(upgrade): ensure downgraded components are created in the Angular zone (#18209)
PR Close #18209
This commit is contained in:

committed by
Miško Hevery

parent
6d7799fce9
commit
43c33d5663
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ComponentFactory, ComponentFactoryResolver, Injector, Type} from '@angular/core';
|
||||
import {ComponentFactory, ComponentFactoryResolver, Injector, NgZone, Type} from '@angular/core';
|
||||
|
||||
import * as angular from './angular1';
|
||||
import {$COMPILE, $INJECTOR, $PARSE, INJECTOR_KEY, LAZY_MODULE_REF, REQUIRE_INJECTOR, REQUIRE_NG_MODEL} from './constants';
|
||||
@ -72,6 +72,14 @@ export function downgradeComponent(info: {
|
||||
$compile: angular.ICompileService,
|
||||
$injector: angular.IInjectorService,
|
||||
$parse: angular.IParseService): angular.IDirective {
|
||||
// When using `UpgradeModule`, we don't need to ensure callbacks to Angular APIs (e.g. change
|
||||
// detection) are run inside the Angular zone, because `$digest()` will be run inside the zone
|
||||
// (except if explicitly escaped, in which case we shouldn't force it back in).
|
||||
// When using `downgradeModule()` though, we need to ensure such callbacks are run inside the
|
||||
// Angular zone.
|
||||
let needsNgZone = false;
|
||||
let wrapCallback = <T>(cb: () => T) => cb;
|
||||
let ngZone: NgZone;
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
@ -89,10 +97,11 @@ export function downgradeComponent(info: {
|
||||
|
||||
if (!parentInjector) {
|
||||
const lazyModuleRef = $injector.get(LAZY_MODULE_REF) as LazyModuleRef;
|
||||
parentInjector = lazyModuleRef.injector || lazyModuleRef.promise;
|
||||
needsNgZone = lazyModuleRef.needsNgZone;
|
||||
parentInjector = lazyModuleRef.injector || lazyModuleRef.promise as Promise<Injector>;
|
||||
}
|
||||
|
||||
const downgradeFn = (injector: Injector) => {
|
||||
const doDowngrade = (injector: Injector) => {
|
||||
const componentFactoryResolver: ComponentFactoryResolver =
|
||||
injector.get(ComponentFactoryResolver);
|
||||
const componentFactory: ComponentFactory<any> =
|
||||
@ -106,13 +115,13 @@ export function downgradeComponent(info: {
|
||||
const injectorPromise = new ParentInjectorPromise(element);
|
||||
const facade = new DowngradeComponentAdapter(
|
||||
id, element, attrs, scope, ngModel, injector, $injector, $compile, $parse,
|
||||
componentFactory);
|
||||
componentFactory, wrapCallback);
|
||||
|
||||
const projectableNodes = facade.compileContents();
|
||||
facade.createComponent(projectableNodes);
|
||||
facade.setupInputs(info.propagateDigest);
|
||||
facade.setupInputs(needsNgZone, info.propagateDigest);
|
||||
facade.setupOutputs();
|
||||
facade.registerCleanup();
|
||||
facade.registerCleanup(needsNgZone);
|
||||
|
||||
injectorPromise.resolve(facade.getInjector());
|
||||
|
||||
@ -123,6 +132,16 @@ export function downgradeComponent(info: {
|
||||
}
|
||||
};
|
||||
|
||||
const downgradeFn = !needsNgZone ? doDowngrade : (injector: Injector) => {
|
||||
if (!ngZone) {
|
||||
ngZone = injector.get(NgZone);
|
||||
wrapCallback = <T>(cb: () => T) => () =>
|
||||
NgZone.isInAngularZone() ? cb() : ngZone.run(cb);
|
||||
}
|
||||
|
||||
wrapCallback(() => doDowngrade(injector))();
|
||||
};
|
||||
|
||||
if (isThenable<Injector>(parentInjector)) {
|
||||
parentInjector.then(downgradeFn);
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user