fix(upgrade): ensure downgraded components are destroyed in the Angular zone

This commit is contained in:
George Kalpakas 2017-09-25 12:39:51 +03:00 committed by Alex Rickabaugh
parent 745b59f49c
commit 4e6aa9c2db
3 changed files with 42 additions and 4 deletions

View File

@ -203,11 +203,13 @@ export class DowngradeComponentAdapter {
} }
registerCleanup(needsNgZone: boolean) { registerCleanup(needsNgZone: boolean) {
const destroyComponentRef = this.wrapCallback(() => this.componentRef.destroy());
this.element.on !('$destroy', () => { this.element.on !('$destroy', () => {
this.componentScope.$destroy(); this.componentScope.$destroy();
this.componentRef.injector.get(TestabilityRegistry) this.componentRef.injector.get(TestabilityRegistry)
.unregisterApplication(this.componentRef.location.nativeElement); .unregisterApplication(this.componentRef.location.nativeElement);
this.componentRef.destroy(); destroyComponentRef();
if (needsNgZone) { if (needsNgZone) {
this.appRef.detachView(this.componentRef.hostView); this.appRef.detachView(this.componentRef.hostView);
} }

View File

@ -122,7 +122,7 @@ export function main() {
let $compile = undefined as any; let $compile = undefined as any;
let $parse = undefined as any; let $parse = undefined as any;
let componentFactory: ComponentFactory<any>; // testbed let componentFactory: ComponentFactory<any>; // testbed
let wrapCallback = undefined as any; let wrapCallback = (cb: any) => cb;
content = ` content = `
<h1> new component </h1> <h1> new component </h1>
@ -183,7 +183,7 @@ export function main() {
expect(registry.getAllTestabilities().length).toEqual(0); expect(registry.getAllTestabilities().length).toEqual(0);
adapter.createComponent([]); adapter.createComponent([]);
expect(registry.getAllTestabilities().length).toEqual(1); expect(registry.getAllTestabilities().length).toEqual(1);
adapter.registerCleanup(true); adapter.registerCleanup();
element.remove !(); element.remove !();
expect(registry.getAllTestabilities().length).toEqual(0); expect(registry.getAllTestabilities().length).toEqual(0);
}); });

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {Component, Inject, Injector, Input, NgModule, NgZone, OnChanges, StaticProvider, destroyPlatform} from '@angular/core'; import {Component, Inject, Injector, Input, NgModule, NgZone, OnChanges, OnDestroy, StaticProvider, destroyPlatform} from '@angular/core';
import {async, fakeAsync, tick} from '@angular/core/testing'; import {async, fakeAsync, tick} from '@angular/core/testing';
import {BrowserModule} from '@angular/platform-browser'; import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
@ -170,6 +170,42 @@ export function main() {
}); });
})); }));
it('should destroy components inside the Angular zone', async(() => {
let destroyedInTheZone = false;
@Component({selector: 'ng2', template: ''})
class Ng2Component implements OnDestroy {
ngOnDestroy() { destroyedInTheZone = NgZone.isInAngularZone(); }
}
@NgModule({
declarations: [Ng2Component],
entryComponents: [Ng2Component],
imports: [BrowserModule],
})
class Ng2Module {
ngDoBootstrap() {}
}
const bootstrapFn = (extraProviders: StaticProvider[]) =>
platformBrowserDynamic(extraProviders).bootstrapModule(Ng2Module);
const lazyModuleName = downgradeModule<Ng2Module>(bootstrapFn);
const ng1Module =
angular.module('ng1', [lazyModuleName])
.directive(
'ng2', downgradeComponent({component: Ng2Component, propagateDigest}));
const element = html('<ng2 ng-if="!hideNg2"></ng2>');
const $injector = angular.bootstrap(element, [ng1Module.name]);
const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService;
// Wait for the module to be bootstrapped.
setTimeout(() => {
$rootScope.$apply('hideNg2 = true');
expect(destroyedInTheZone).toBe(true);
});
}));
it('should propagate input changes inside the Angular zone', async(() => { it('should propagate input changes inside the Angular zone', async(() => {
let ng2Component: Ng2Component; let ng2Component: Ng2Component;