diff --git a/modules/@angular/compiler/src/animation/animation_compiler.ts b/modules/@angular/compiler/src/animation/animation_compiler.ts
index 66682d7170..6f85494842 100644
--- a/modules/@angular/compiler/src/animation/animation_compiler.ts
+++ b/modules/@angular/compiler/src/animation/animation_compiler.ts
@@ -294,8 +294,8 @@ class _AnimationBuilder implements AnimationAstVisitor {
statements.push(new o.ReturnStatement(
o.importExpr(createIdentifier(Identifiers.AnimationTransition)).instantiate([
- _ANIMATION_PLAYER_VAR, _ANIMATION_CURRENT_STATE_VAR, _ANIMATION_NEXT_STATE_VAR,
- _ANIMATION_TIME_VAR
+ _ANIMATION_PLAYER_VAR, _ANIMATION_FACTORY_ELEMENT_VAR, _ANIMATION_CURRENT_STATE_VAR,
+ _ANIMATION_NEXT_STATE_VAR, _ANIMATION_TIME_VAR
])));
return o.fn(
diff --git a/modules/@angular/core/src/animation/animation_transition.ts b/modules/@angular/core/src/animation/animation_transition.ts
index eaea2efb2c..772f7789f1 100644
--- a/modules/@angular/core/src/animation/animation_transition.ts
+++ b/modules/@angular/core/src/animation/animation_transition.ts
@@ -5,20 +5,23 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
+import {ElementRef} from '../linker/element_ref';
+
import {AnimationPlayer} from './animation_player';
import {AnimationTransitionEvent} from './animation_transition_event';
export class AnimationTransition {
constructor(
- private _player: AnimationPlayer, private _fromState: string, private _toState: string,
- private _totalTime: number) {}
+ private _player: AnimationPlayer, private _element: ElementRef, private _fromState: string,
+ private _toState: string, private _totalTime: number) {}
private _createEvent(phaseName: string): AnimationTransitionEvent {
return new AnimationTransitionEvent({
fromState: this._fromState,
toState: this._toState,
totalTime: this._totalTime,
- phaseName: phaseName
+ phaseName: phaseName,
+ element: this._element
});
}
diff --git a/modules/@angular/core/src/animation/animation_transition_event.ts b/modules/@angular/core/src/animation/animation_transition_event.ts
index dfc6d6dc48..ccea8dbc5f 100644
--- a/modules/@angular/core/src/animation/animation_transition_event.ts
+++ b/modules/@angular/core/src/animation/animation_transition_event.ts
@@ -5,6 +5,7 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
+import {ElementRef} from '../linker/element_ref';
/**
* An instance of this class is returned as an event parameter when an animation
@@ -42,12 +43,19 @@ export class AnimationTransitionEvent {
public toState: string;
public totalTime: number;
public phaseName: string;
+ public element: ElementRef;
- constructor({fromState, toState, totalTime, phaseName}:
- {fromState: string, toState: string, totalTime: number, phaseName: string}) {
+ constructor({fromState, toState, totalTime, phaseName, element}: {
+ fromState: string,
+ toState: string,
+ totalTime: number,
+ phaseName: string,
+ element: any
+ }) {
this.fromState = fromState;
this.toState = toState;
this.totalTime = totalTime;
this.phaseName = phaseName;
+ this.element = new ElementRef(element);
}
}
diff --git a/modules/@angular/core/test/animation/animation_integration_spec.ts b/modules/@angular/core/test/animation/animation_integration_spec.ts
index 955ba9258e..710ae00b54 100644
--- a/modules/@angular/core/test/animation/animation_integration_spec.ts
+++ b/modules/@angular/core/test/animation/animation_integration_spec.ts
@@ -27,6 +27,7 @@ import {AnimationTransitionEvent} from '../../src/animation/animation_transition
import {AUTO_STYLE, animate, group, keyframes, sequence, state, style, transition, trigger} from '../../src/animation/metadata';
import {Input} from '../../src/core';
import {isPresent} from '../../src/facade/lang';
+import {ElementRef} from '../../src/linker/element_ref';
import {TestBed, fakeAsync, flushMicrotasks} from '../../testing';
import {MockAnimationPlayer} from '../../testing/mock_animation_player';
@@ -1763,6 +1764,36 @@ function declareTests({useJit}: {useJit: boolean}) {
expect(doneCalls[3]).toEqual(1);
expect(doneCalls[4]).toEqual(1);
}));
+
+ it('should expose the element associated with the animation within the callback event',
+ fakeAsync(() => {
+ TestBed.overrideComponent(DummyIfCmp, {
+ set: {
+ template: `
+
{{ item }}
+ `,
+ animations: [trigger('trigger', [transition('* => *', [animate(1000)])])]
+ }
+ });
+
+ const fixture = TestBed.createComponent(DummyIfCmp);
+ const cmp = fixture.componentInstance;
+
+ const elements: ElementRef[] = [];
+ cmp.callback = (e: AnimationTransitionEvent) => elements.push(e.element);
+
+ cmp.items = [0, 1, 2, 3, 4];
+ fixture.detectChanges();
+ flushMicrotasks();
+
+ const targetElements =
+ getDOM().querySelectorAll(fixture.nativeElement, '.target');
+ for (let i = 0; i < elements.length; i++) {
+ expect(elements[i].nativeElement).toBe(targetElements[i]);
+ }
+ }));
});
describe('ng directives', () => {
diff --git a/modules/@angular/platform-webworker/test/web_workers/worker/renderer_animation_integration_spec.ts b/modules/@angular/platform-webworker/test/web_workers/worker/renderer_animation_integration_spec.ts
index f0507b15e1..bea50582d8 100644
--- a/modules/@angular/platform-webworker/test/web_workers/worker/renderer_animation_integration_spec.ts
+++ b/modules/@angular/platform-webworker/test/web_workers/worker/renderer_animation_integration_spec.ts
@@ -8,6 +8,8 @@
import {AUTO_STYLE, AnimationTransitionEvent, Component, Injector, ViewChild, animate, state, style, transition, trigger} from '@angular/core';
import {DebugDomRootRenderer} from '@angular/core/src/debug/debug_renderer';
+import {ElementRef} from '@angular/core/src/linker/element_ref';
+import {ViewChild} from '@angular/core/src/metadata/di';
import {RootRenderer} from '@angular/core/src/render/api';
import {TestBed, fakeAsync, flushMicrotasks} from '@angular/core/testing';
import {MockAnimationPlayer} from '@angular/core/testing/testing_internal';
@@ -203,24 +205,34 @@ export function main() {
flushMicrotasks();
uiDriver.log.shift()['player'].finish();
- const [triggerOneStart, triggerOneDone] = log['one'];
- expect(triggerOneStart)
- .toEqual(new AnimationTransitionEvent(
- {fromState: 'a', toState: 'b', totalTime: 500, phaseName: 'start'}));
- expect(triggerOneDone)
- .toEqual(new AnimationTransitionEvent(
- {fromState: 'a', toState: 'b', totalTime: 500, phaseName: 'done'}));
+ const [triggerOneStart, triggerOneDone] = log['one'];
+ expect(triggerOneStart.fromState).toEqual('a');
+ expect(triggerOneStart.toState).toEqual('b');
+ expect(triggerOneStart.totalTime).toEqual(500);
+ expect(triggerOneStart.phaseName).toEqual('start');
+ expect(triggerOneStart.element instanceof ElementRef).toEqual(true);
+
+ expect(triggerOneDone.fromState).toEqual('a');
+ expect(triggerOneDone.toState).toEqual('b');
+ expect(triggerOneDone.totalTime).toEqual(500);
+ expect(triggerOneDone.phaseName).toEqual('done');
+ expect(triggerOneDone.element instanceof ElementRef).toEqual(true);
uiDriver.log.shift()['player'].finish();
- const [triggerTwoStart, triggerTwoDone] = log['two'];
- expect(triggerTwoStart)
- .toEqual(new AnimationTransitionEvent(
- {fromState: 'c', toState: 'd', totalTime: 1000, phaseName: 'start'}));
- expect(triggerTwoDone)
- .toEqual(new AnimationTransitionEvent(
- {fromState: 'c', toState: 'd', totalTime: 1000, phaseName: 'done'}));
+ const [triggerTwoStart, triggerTwoDone] = log['two'];
+ expect(triggerTwoStart.fromState).toEqual('c');
+ expect(triggerTwoStart.toState).toEqual('d');
+ expect(triggerTwoStart.totalTime).toEqual(1000);
+ expect(triggerTwoStart.phaseName).toEqual('start');
+ expect(triggerTwoStart.element instanceof ElementRef).toEqual(true);
+
+ expect(triggerTwoDone.fromState).toEqual('c');
+ expect(triggerTwoDone.toState).toEqual('d');
+ expect(triggerTwoDone.totalTime).toEqual(1000);
+ expect(triggerTwoDone.phaseName).toEqual('done');
+ expect(triggerTwoDone.element instanceof ElementRef).toEqual(true);
}));
it('should handle .start and .done callbacks for mutliple elements that contain animations that are fired at the same time',
@@ -228,7 +240,7 @@ export function main() {
function logFactory(
log: {[phaseName: string]: AnimationTransitionEvent},
phaseName: string): (event: AnimationTransitionEvent) => any {
- return (event: AnimationTransitionEvent) => { log[phaseName] = event; };
+ return (event: AnimationTransitionEvent) => log[phaseName] = event;
}
const fixture = TestBed.createComponent(ContainerAnimationCmp);
@@ -250,25 +262,37 @@ export function main() {
uiDriver.log.shift()['player'].finish();
- expect(cmp1Log['start'])
- .toEqual(new AnimationTransitionEvent(
- {fromState: 'void', toState: 'off', totalTime: 500, phaseName: 'start'}));
+ const start1 = cmp1Log['start'];
+ expect(start1.fromState).toEqual('void');
+ expect(start1.toState).toEqual('off');
+ expect(start1.totalTime).toEqual(500);
+ expect(start1.phaseName).toEqual('start');
+ expect(start1.element instanceof ElementRef).toBe(true);
- expect(cmp1Log['done'])
- .toEqual(new AnimationTransitionEvent(
- {fromState: 'void', toState: 'off', totalTime: 500, phaseName: 'done'}));
+ const done1 = cmp1Log['done'];
+ expect(done1.fromState).toEqual('void');
+ expect(done1.toState).toEqual('off');
+ expect(done1.totalTime).toEqual(500);
+ expect(done1.phaseName).toEqual('done');
+ expect(done1.element instanceof ElementRef).toBe(true);
// the * => on transition has two steps
uiDriver.log.shift()['player'].finish();
uiDriver.log.shift()['player'].finish();
- expect(cmp2Log['start'])
- .toEqual(new AnimationTransitionEvent(
- {fromState: 'void', toState: 'on', totalTime: 1000, phaseName: 'start'}));
+ const start2 = cmp2Log['start'];
+ expect(start2.fromState).toEqual('void');
+ expect(start2.toState).toEqual('on');
+ expect(start2.totalTime).toEqual(1000);
+ expect(start2.phaseName).toEqual('start');
+ expect(start2.element instanceof ElementRef).toBe(true);
- expect(cmp2Log['done'])
- .toEqual(new AnimationTransitionEvent(
- {fromState: 'void', toState: 'on', totalTime: 1000, phaseName: 'done'}));
+ const done2 = cmp2Log['done'];
+ expect(done2.fromState).toEqual('void');
+ expect(done2.toState).toEqual('on');
+ expect(done2.totalTime).toEqual(1000);
+ expect(done2.phaseName).toEqual('done');
+ expect(done2.element instanceof ElementRef).toBe(true);
}));
it('should destroy the player when the animation is complete', fakeAsync(() => {
@@ -331,6 +355,7 @@ class ContainerAnimationCmp {
selector: 'my-comp',
template: `
...
@@ -348,6 +373,8 @@ class AnimationCmp {
state = 'off';
stateStartFn = (event: AnimationTransitionEvent): any => {};
stateDoneFn = (event: AnimationTransitionEvent): any => {};
+
+ @ViewChild('ref') public elmRef: ElementRef;
}
@Component({
@@ -355,10 +382,10 @@ class AnimationCmp {
template: `
...
+ (@one.done)="callback('one', $event)" #one>...
...
+ (@two.done)="callback('two', $event)" #two>...
`,
animations: [
trigger(
@@ -378,5 +405,10 @@ class AnimationCmp {
class MultiAnimationCmp {
oneTriggerState: string;
twoTriggerState: string;
+
+ @ViewChild('one') public elmRef1: ElementRef;
+
+ @ViewChild('two') public elmRef2: ElementRef;
+
callback = (triggerName: string, event: AnimationTransitionEvent): any => {};
}
diff --git a/tools/public_api_guard/core/index.d.ts b/tools/public_api_guard/core/index.d.ts
index b1d0a9da31..56ed6e3dbd 100644
--- a/tools/public_api_guard/core/index.d.ts
+++ b/tools/public_api_guard/core/index.d.ts
@@ -108,15 +108,17 @@ export declare class AnimationStyleMetadata extends AnimationMetadata {
/** @experimental */
export declare class AnimationTransitionEvent {
+ element: ElementRef;
fromState: string;
phaseName: string;
toState: string;
totalTime: number;
- constructor({fromState, toState, totalTime, phaseName}: {
+ constructor({fromState, toState, totalTime, phaseName, element}: {
fromState: string;
toState: string;
totalTime: number;
phaseName: string;
+ element: any;
});
}