fix(animations): ensure :animating
queries collect previous animation elements properly
This commit is contained in:
parent
f85b543cc1
commit
3203639d7d
@ -18,6 +18,9 @@ import {ENTER_CLASSNAME, LEAVE_CLASSNAME, NG_ANIMATING_CLASSNAME, NG_ANIMATING_S
|
|||||||
import {AnimationDriver} from './animation_driver';
|
import {AnimationDriver} from './animation_driver';
|
||||||
import {getOrSetAsInMap, listenOnPlayer, makeAnimationEvent, normalizeKeyframes, optimizeGroupPlayer} from './shared';
|
import {getOrSetAsInMap, listenOnPlayer, makeAnimationEvent, normalizeKeyframes, optimizeGroupPlayer} from './shared';
|
||||||
|
|
||||||
|
const QUEUED_CLASSNAME = 'ng-animate-queued';
|
||||||
|
const QUEUED_SELECTOR = '.ng-animate-queued';
|
||||||
|
|
||||||
const EMPTY_PLAYER_ARRAY: TransitionAnimationPlayer[] = [];
|
const EMPTY_PLAYER_ARRAY: TransitionAnimationPlayer[] = [];
|
||||||
const NULL_REMOVAL_STATE: ElementAnimationState = {
|
const NULL_REMOVAL_STATE: ElementAnimationState = {
|
||||||
namespaceId: '',
|
namespaceId: '',
|
||||||
@ -235,12 +238,11 @@ export class AnimationTransitionNamespace {
|
|||||||
{element, triggerName, transition, fromState, toState, player, isFallbackTransition});
|
{element, triggerName, transition, fromState, toState, player, isFallbackTransition});
|
||||||
|
|
||||||
if (!isFallbackTransition) {
|
if (!isFallbackTransition) {
|
||||||
addClass(element, NG_ANIMATING_CLASSNAME);
|
addClass(element, QUEUED_CLASSNAME);
|
||||||
|
player.onStart(() => { removeClass(element, QUEUED_CLASSNAME); });
|
||||||
}
|
}
|
||||||
|
|
||||||
player.onDone(() => {
|
player.onDone(() => {
|
||||||
removeClass(element, NG_ANIMATING_CLASSNAME);
|
|
||||||
|
|
||||||
let index = this.players.indexOf(player);
|
let index = this.players.indexOf(player);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
this.players.splice(index, 1);
|
this.players.splice(index, 1);
|
||||||
|
@ -39,7 +39,7 @@ export function main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('query()', () => {
|
describe('query()', () => {
|
||||||
it('should be able to query all animation triggers via `@*`', () => {
|
it('should be able to query all elements that contain animation triggers via @*', () => {
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ani-cmp',
|
selector: 'ani-cmp',
|
||||||
template: `
|
template: `
|
||||||
@ -56,30 +56,40 @@ export function main() {
|
|||||||
'parent',
|
'parent',
|
||||||
[
|
[
|
||||||
transition(
|
transition(
|
||||||
'* => *',
|
'* => go',
|
||||||
[
|
[
|
||||||
query(
|
query(
|
||||||
'@*:animating',
|
'@*',
|
||||||
[
|
[
|
||||||
animate(1000, style({background: 'red'})),
|
style({ backgroundColor: 'blue' }),
|
||||||
|
animate(1000, style({backgroundColor: 'red'})),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
trigger(
|
trigger(
|
||||||
'a',
|
'a',
|
||||||
[
|
[
|
||||||
transition('* => *', []),
|
transition('* => 1', [
|
||||||
|
animate(1000, style({ opacity: 0 }))
|
||||||
|
]),
|
||||||
]),
|
]),
|
||||||
trigger(
|
trigger(
|
||||||
'b',
|
'b',
|
||||||
[
|
[
|
||||||
transition('* => *', []),
|
transition('* => 1', [
|
||||||
|
animate(1000, style({ opacity: 0 })),
|
||||||
|
query('.b-inner', [
|
||||||
|
animate(1000, style({ opacity: 0 }))
|
||||||
|
]),
|
||||||
|
]),
|
||||||
]),
|
]),
|
||||||
trigger(
|
trigger(
|
||||||
'c',
|
'c',
|
||||||
[
|
[
|
||||||
transition('* => *', []),
|
transition('* => 1', [
|
||||||
])
|
animate(1000, style({ opacity: 0 }))
|
||||||
|
]),
|
||||||
|
]),
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
class Cmp {
|
class Cmp {
|
||||||
@ -90,23 +100,117 @@ export function main() {
|
|||||||
|
|
||||||
TestBed.configureTestingModule({declarations: [Cmp]});
|
TestBed.configureTestingModule({declarations: [Cmp]});
|
||||||
|
|
||||||
const engine = TestBed.get(ɵAnimationEngine);
|
|
||||||
const fixture = TestBed.createComponent(Cmp);
|
const fixture = TestBed.createComponent(Cmp);
|
||||||
const cmp = fixture.componentInstance;
|
const cmp = fixture.componentInstance;
|
||||||
|
|
||||||
cmp.exp0 = 1;
|
cmp.exp0 = 'go';
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
let players = getLog();
|
||||||
|
expect(players.length).toEqual(3); // a,b,c
|
||||||
|
resetLog();
|
||||||
|
|
||||||
|
const [p1, p2, p3] = players;
|
||||||
|
expect(p1.element.classList.contains('a')).toBeTruthy();
|
||||||
|
expect(p2.element.classList.contains('b')).toBeTruthy();
|
||||||
|
expect(p3.element.classList.contains('c')).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to query currently animating elements via :animating', () => {
|
||||||
|
@Component({
|
||||||
|
selector: 'ani-cmp',
|
||||||
|
template: `
|
||||||
|
<div [@parent]="exp0">
|
||||||
|
<div class="a" [@a]="exp1"></div>
|
||||||
|
<div class="b" [@b]="exp2">
|
||||||
|
<div class="b-inner"></div>
|
||||||
|
</div>
|
||||||
|
<div class="c" [@c]="exp3"></div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
animations: [
|
||||||
|
trigger(
|
||||||
|
'parent',
|
||||||
|
[
|
||||||
|
transition(
|
||||||
|
'* => go',
|
||||||
|
[
|
||||||
|
query(
|
||||||
|
':animating',
|
||||||
|
[
|
||||||
|
style({ backgroundColor: 'blue' }),
|
||||||
|
animate(1000, style({backgroundColor: 'red'})),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
trigger(
|
||||||
|
'a',
|
||||||
|
[
|
||||||
|
transition('* => 1', [
|
||||||
|
animate(1000, style({ opacity: 0 }))
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
trigger(
|
||||||
|
'b',
|
||||||
|
[
|
||||||
|
transition('* => 1', [
|
||||||
|
animate(1000, style({ opacity: 0 })),
|
||||||
|
query('.b-inner', [
|
||||||
|
animate(1000, style({ opacity: 0 }))
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
trigger(
|
||||||
|
'c',
|
||||||
|
[
|
||||||
|
transition('* => 1', [
|
||||||
|
animate(1000, style({ opacity: 0 }))
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
})
|
||||||
|
class Cmp {
|
||||||
|
public exp0: any;
|
||||||
|
public exp1: any;
|
||||||
|
public exp2: any;
|
||||||
|
public exp3: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [Cmp]});
|
||||||
|
|
||||||
|
const fixture = TestBed.createComponent(Cmp);
|
||||||
|
const cmp = fixture.componentInstance;
|
||||||
|
|
||||||
|
cmp.exp0 = '';
|
||||||
cmp.exp1 = 1;
|
cmp.exp1 = 1;
|
||||||
cmp.exp2 = 1;
|
cmp.exp2 = 1;
|
||||||
|
// note that exp3 is skipped here
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
engine.flush();
|
|
||||||
|
|
||||||
const players = getLog();
|
let players = getLog();
|
||||||
|
expect(players.length).toEqual(3); // a,b,b-inner and not c
|
||||||
|
resetLog();
|
||||||
|
|
||||||
|
cmp.exp0 = 'go';
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const expectedKeyframes = [
|
||||||
|
{backgroundColor: 'blue', offset: 0},
|
||||||
|
{backgroundColor: 'red', offset: 1},
|
||||||
|
];
|
||||||
|
|
||||||
|
players = getLog();
|
||||||
expect(players.length).toEqual(3);
|
expect(players.length).toEqual(3);
|
||||||
const [p1, p2, p3] = players;
|
const [p1, p2, p3] = players;
|
||||||
|
|
||||||
expect(p1.element.classList.contains('a')).toBeTruthy();
|
expect(p1.element.classList.contains('a')).toBeTruthy();
|
||||||
|
expect(p1.keyframes).toEqual(expectedKeyframes);
|
||||||
|
|
||||||
expect(p2.element.classList.contains('b')).toBeTruthy();
|
expect(p2.element.classList.contains('b')).toBeTruthy();
|
||||||
expect(p3.element.classList.contains('c')).toBeTruthy();
|
expect(p2.keyframes).toEqual(expectedKeyframes);
|
||||||
|
|
||||||
|
expect(p3.element.classList.contains('b-inner')).toBeTruthy();
|
||||||
|
expect(p3.keyframes).toEqual(expectedKeyframes);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to query triggers directly by name', () => {
|
it('should be able to query triggers directly by name', () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user