fix(upgrade): properly destroy upgraded component elements and descendants (#26209)

Fixes #26208

PR Close #26209
This commit is contained in:
Jason Bedard
2018-10-01 21:29:38 -07:00
committed by Jason Aden
parent decc0b840d
commit 5a31bde649
4 changed files with 307 additions and 9 deletions

View File

@ -223,14 +223,17 @@ let angular: {
bootstrap: (e: Element, modules: (string | IInjectable)[], config?: IAngularBootstrapConfig) =>
IInjectorService,
module: (prefix: string, dependencies?: string[]) => IModule,
element: (e: string | Element | Document | IAugmentedJQuery) => IAugmentedJQuery,
element: {
(e: string | Element | Document | IAugmentedJQuery): IAugmentedJQuery;
cleanData: (nodes: Node[] | NodeList) => void;
},
version: {major: number},
resumeBootstrap: () => void,
getTestability: (e: Element) => ITestabilityService
} = <any>{
bootstrap: noNg,
module: noNg,
element: noNg,
element: Object.assign(() => noNg(), {cleanData: noNg}),
version: undefined,
resumeBootstrap: noNg,
getTestability: noNg
@ -281,7 +284,9 @@ export const bootstrap: typeof angular.bootstrap = (e, modules, config?) =>
export const module: typeof angular.module = (prefix, dependencies?) =>
angular.module(prefix, dependencies);
export const element: typeof angular.element = e => angular.element(e);
export const element: typeof angular.element = Object.assign(
(e: string | Element | Document | IAugmentedJQuery) => angular.element(e),
{cleanData: (nodes: Node[] | NodeList) => angular.element.cleanData(nodes)});
export const resumeBootstrap: typeof angular.resumeBootstrap = () => angular.resumeBootstrap();

View File

@ -124,7 +124,15 @@ export class UpgradeHelper {
controllerInstance.$onDestroy();
}
$scope.$destroy();
this.$element.triggerHandler !('$destroy');
// Clean the jQuery/jqLite data on the component+child elements.
// Equivelent to how jQuery/jqLite invoke `cleanData` on an Element (this.element)
// https://github.com/jquery/jquery/blob/e743cbd28553267f955f71ea7248377915613fd9/src/manipulation.js#L223
// https://github.com/angular/angular.js/blob/26ddc5f830f902a3d22f4b2aab70d86d4d688c82/src/jqLite.js#L306-L312
// `cleanData` will invoke the AngularJS `$destroy` DOM event
// https://github.com/angular/angular.js/blob/26ddc5f830f902a3d22f4b2aab70d86d4d688c82/src/Angular.js#L1911-L1924
angular.element.cleanData([this.element]);
angular.element.cleanData(this.element.querySelectorAll('*'));
}
prepareTransclusion(): angular.ILinkFn|undefined {