From ba88db5141fdab859ccd5437eba3a561e2ad3100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Tue, 26 Jul 2016 15:20:27 -0700 Subject: [PATCH] fix(ngClass): do not deconstruct classes on element removal (#10303) Prior to this fix [ngClass] would remove all dynamic classes when destroyed. It's essential that classes are persisted such that remove-based animations will still be stylistically correct. This patch fixes this issue. Closes #10008 Closes #10303 --- .../common/src/directives/ng_class.ts | 6 ++-- .../animation/animation_integration_spec.ts | 33 +++++++++++++++++++ tools/public_api_guard/common/index.d.ts | 3 +- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/modules/@angular/common/src/directives/ng_class.ts b/modules/@angular/common/src/directives/ng_class.ts index baf1e0b641..823faf69ba 100644 --- a/modules/@angular/common/src/directives/ng_class.ts +++ b/modules/@angular/common/src/directives/ng_class.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {CollectionChangeRecord, Directive, DoCheck, ElementRef, Input, IterableDiffer, IterableDiffers, KeyValueChangeRecord, KeyValueDiffer, KeyValueDiffers, OnDestroy, Renderer} from '@angular/core'; +import {CollectionChangeRecord, Directive, DoCheck, ElementRef, Input, IterableDiffer, IterableDiffers, KeyValueChangeRecord, KeyValueDiffer, KeyValueDiffers, Renderer} from '@angular/core'; import {StringMapWrapper, isListLikeIterable} from '../facade/collection'; import {isArray, isPresent, isString} from '../facade/lang'; @@ -75,7 +75,7 @@ import {isArray, isPresent, isString} from '../facade/lang'; * @stable */ @Directive({selector: '[ngClass]'}) -export class NgClass implements DoCheck, OnDestroy { +export class NgClass implements DoCheck { private _iterableDiffer: IterableDiffer; private _keyValueDiffer: KeyValueDiffer; private _initialClasses: string[] = []; @@ -129,8 +129,6 @@ export class NgClass implements DoCheck, OnDestroy { } } - ngOnDestroy(): void { this._cleanupClasses(this._rawClass); } - private _cleanupClasses(rawClassVal: string[]|Set|{[key: string]: any}): void { this._applyClasses(rawClassVal, true); this._applyInitialClasses(false); diff --git a/modules/@angular/core/test/animation/animation_integration_spec.ts b/modules/@angular/core/test/animation/animation_integration_spec.ts index 80419e233d..66a2cb4737 100644 --- a/modules/@angular/core/test/animation/animation_integration_spec.ts +++ b/modules/@angular/core/test/animation/animation_integration_spec.ts @@ -874,6 +874,39 @@ function declareTests({useJit}: {useJit: boolean}) { }))); }); + describe('ng directives', () => { + describe('[ngClass]', () => { + it('should persist ngClass class values when a remove element animation is active', + inject( + [TestComponentBuilder, AnimationDriver], + fakeAsync( + (tcb: TestComponentBuilder, driver: InnerContentTrackingAnimationDriver) => { + makeAnimationCmp( + tcb, `
`, + [ + trigger('trigger', [transition('* => void', [animate(1000)])]), + ], + (fixture: any /** TODO #9100 */) => { + var cmp = fixture.debugElement.componentInstance; + cmp.exp = true; + cmp.exp2 = 'blue'; + fixture.detectChanges(); + flushMicrotasks(); + + expect(driver.log.length).toEqual(0); + + cmp.exp = false; + fixture.detectChanges(); + flushMicrotasks(); + + var animation = driver.log.pop(); + var element = animation['element']; + (expect(element)).toHaveCssClass('blue'); + }); + }))); + }); + }); + describe('animation states', () => { it('should throw an error when an animation is referenced that isn\'t defined within the component annotation', inject( diff --git a/tools/public_api_guard/common/index.d.ts b/tools/public_api_guard/common/index.d.ts index a90668e565..a30c5e8e80 100644 --- a/tools/public_api_guard/common/index.d.ts +++ b/tools/public_api_guard/common/index.d.ts @@ -291,14 +291,13 @@ export declare const NG_VALIDATORS: OpaqueToken; export declare const NG_VALUE_ACCESSOR: OpaqueToken; /** @stable */ -export declare class NgClass implements DoCheck, OnDestroy { +export declare class NgClass implements DoCheck { initialClasses: string; ngClass: string | string[] | Set | { [key: string]: any; }; constructor(_iterableDiffers: IterableDiffers, _keyValueDiffers: KeyValueDiffers, _ngEl: ElementRef, _renderer: Renderer); ngDoCheck(): void; - ngOnDestroy(): void; } /** @experimental */