diff --git a/packages/animations/browser/src/render/animation_engine_next.ts b/packages/animations/browser/src/render/animation_engine_next.ts index f34f17273d4..080c7c04a1f 100644 --- a/packages/animations/browser/src/render/animation_engine_next.ts +++ b/packages/animations/browser/src/render/animation_engine_next.ts @@ -72,8 +72,8 @@ export class AnimationEngine { this._transitionEngine.insertNode(namespaceId, element, parent, insertBefore); } - onRemove(namespaceId: string, element: any, context: any, isHostElement?: boolean): void { - this._transitionEngine.removeNode(namespaceId, element, isHostElement || false, context); + onRemove(namespaceId: string, element: any, context: any): void { + this._transitionEngine.removeNode(namespaceId, element, context); } disableAnimations(element: any, disable: boolean) { diff --git a/packages/animations/browser/src/render/transition_animation_engine.ts b/packages/animations/browser/src/render/transition_animation_engine.ts index 6b861945f2d..e30b43277f6 100644 --- a/packages/animations/browser/src/render/transition_animation_engine.ts +++ b/packages/animations/browser/src/render/transition_animation_engine.ts @@ -744,7 +744,7 @@ export class TransitionAnimationEngine { } } - removeNode(namespaceId: string, element: any, isHostElement: boolean, context: any): void { + removeNode(namespaceId: string, element: any, context: any): void { if (isElementNode(element)) { const ns = namespaceId ? this._fetchNamespace(namespaceId) : null; if (ns) { @@ -753,11 +753,9 @@ export class TransitionAnimationEngine { this.markElementAsRemoved(namespaceId, element, false, context); } - if (isHostElement) { - const hostNS = this.namespacesByHostElement.get(element); - if (hostNS && hostNS.id !== namespaceId) { - hostNS.removeNode(element, context); - } + const hostNS = this.namespacesByHostElement.get(element); + if (hostNS && hostNS.id !== namespaceId) { + hostNS.removeNode(element, context); } } else { this._onRemovalComplete(element, context); diff --git a/packages/animations/browser/test/render/transition_animation_engine_spec.ts b/packages/animations/browser/test/render/transition_animation_engine_spec.ts index 3e92b0ae34a..cbe5817c18d 100644 --- a/packages/animations/browser/test/render/transition_animation_engine_spec.ts +++ b/packages/animations/browser/test/render/transition_animation_engine_spec.ts @@ -116,7 +116,7 @@ describe('TransitionAnimationEngine', () => { expect(engine.elementContainsData(DEFAULT_NAMESPACE_ID, element)).toBeTruthy(); - engine.removeNode(DEFAULT_NAMESPACE_ID, element, true, true); + engine.removeNode(DEFAULT_NAMESPACE_ID, element, true); engine.flush(); expect(engine.elementContainsData(DEFAULT_NAMESPACE_ID, element)).toBeTruthy(); @@ -171,7 +171,7 @@ describe('TransitionAnimationEngine', () => { expect(engine.statesByElement.has(element)).toBe(true, 'Expected parent data to be defined.'); expect(engine.statesByElement.has(child)).toBe(true, 'Expected child data to be defined.'); - engine.removeNode(DEFAULT_NAMESPACE_ID, element, true, true); + engine.removeNode(DEFAULT_NAMESPACE_ID, element, true); engine.flush(); engine.players[0].finish(); diff --git a/packages/core/test/animation/animation_integration_spec.ts b/packages/core/test/animation/animation_integration_spec.ts index 4f31a10c04f..a55712c207a 100644 --- a/packages/core/test/animation/animation_integration_spec.ts +++ b/packages/core/test/animation/animation_integration_spec.ts @@ -8,7 +8,7 @@ import {animate, animateChild, animation, AnimationEvent, AnimationMetadata, AnimationOptions, AUTO_STYLE, group, keyframes, query, sequence, state, style, transition, trigger, useAnimation, ɵPRE_STYLE as PRE_STYLE} from '@angular/animations'; import {AnimationDriver, ɵAnimationEngine, ɵNoopAnimationDriver as NoopAnimationDriver} from '@angular/animations/browser'; import {MockAnimationDriver, MockAnimationPlayer} from '@angular/animations/browser/testing'; -import {ChangeDetectorRef, Component, HostBinding, HostListener, Inject, RendererFactory2, ViewChild} from '@angular/core'; +import {ChangeDetectorRef, Component, HostBinding, HostListener, Inject, RendererFactory2, ViewChild, ViewContainerRef} from '@angular/core'; import {fakeAsync, flushMicrotasks, TestBed} from '@angular/core/testing'; import {ɵDomRendererFactory2} from '@angular/platform-browser'; import {ANIMATION_MODULE_TYPE, BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations'; @@ -909,6 +909,56 @@ describe('animation tests', function() { ]); })); + it('should trigger a leave animation when the inner has ViewContainerRef injected', + fakeAsync(() => { + @Component({ + selector: 'parent-cmp', + template: ` + + ` + }) + class ParentCmp { + public exp = true; + } + + @Component({ + selector: 'child-cmp', + template: '...', + animations: [trigger( + 'host', + [transition(':leave', [style({opacity: 1}), animate(1000, style({opacity: 0}))])])] + }) + class ChildCmp { + @HostBinding('@host') public hostAnimation = true; + constructor(private vcr: ViewContainerRef) {} + } + + TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]}); + + const engine = TestBed.inject(ɵAnimationEngine); + const fixture = TestBed.createComponent(ParentCmp); + const cmp = fixture.componentInstance; + fixture.detectChanges(); + engine.flush(); + expect(getLog().length).toEqual(0); + + cmp.exp = false; + fixture.detectChanges(); + expect(fixture.debugElement.nativeElement.children.length).toBe(1); + + engine.flush(); + expect(getLog().length).toEqual(1); + + const [player] = getLog(); + expect(player.keyframes).toEqual([ + new Map([['opacity', '1'], ['offset', 0]]), + new Map([['opacity', '0'], ['offset', 1]]), + ]); + + player.finish(); + expect(fixture.debugElement.nativeElement.children.length).toBe(0); + })); + it('should trigger a leave animation when the inner components host binding updates', fakeAsync(() => { @Component({ diff --git a/packages/platform-browser/animations/src/animation_renderer.ts b/packages/platform-browser/animations/src/animation_renderer.ts index 8f4166f7bcb..0a34bdd219c 100644 --- a/packages/platform-browser/animations/src/animation_renderer.ts +++ b/packages/platform-browser/animations/src/animation_renderer.ts @@ -180,7 +180,7 @@ export class BaseAnimationRenderer implements Renderer2 { } removeChild(parent: any, oldChild: any, isHostElement: boolean): void { - this.engine.onRemove(this.namespaceId, oldChild, this.delegate, isHostElement); + this.engine.onRemove(this.namespaceId, oldChild, this.delegate); } selectRootElement(selectorOrNode: any, preserveContent?: boolean) {