fix(animations): stringify boolean values as 1
and 0
(#15311)
Closes #15247 Closes #15311 PR Close #15311
This commit is contained in:
parent
764e90f9bb
commit
94da80148e
@ -31,6 +31,7 @@ export interface TriggerListenerTuple {
|
|||||||
const MARKED_FOR_ANIMATION_CLASSNAME = 'ng-animating';
|
const MARKED_FOR_ANIMATION_CLASSNAME = 'ng-animating';
|
||||||
const MARKED_FOR_ANIMATION_SELECTOR = '.ng-animating';
|
const MARKED_FOR_ANIMATION_SELECTOR = '.ng-animating';
|
||||||
const MARKED_FOR_REMOVAL = '$$ngRemove';
|
const MARKED_FOR_REMOVAL = '$$ngRemove';
|
||||||
|
const VOID_STATE = 'void';
|
||||||
|
|
||||||
export class DomAnimationEngine {
|
export class DomAnimationEngine {
|
||||||
private _flaggedInserts = new Set<any>();
|
private _flaggedInserts = new Set<any>();
|
||||||
@ -84,7 +85,7 @@ export class DomAnimationEngine {
|
|||||||
const possibleTriggers = Object.keys(lookupRef);
|
const possibleTriggers = Object.keys(lookupRef);
|
||||||
const hasRemoval = possibleTriggers.some(triggerName => {
|
const hasRemoval = possibleTriggers.some(triggerName => {
|
||||||
const oldValue = lookupRef[triggerName];
|
const oldValue = lookupRef[triggerName];
|
||||||
const instruction = this._triggers[triggerName].matchTransition(oldValue, 'void');
|
const instruction = this._triggers[triggerName].matchTransition(oldValue, VOID_STATE);
|
||||||
return !!instruction;
|
return !!instruction;
|
||||||
});
|
});
|
||||||
if (hasRemoval) {
|
if (hasRemoval) {
|
||||||
@ -115,8 +116,9 @@ export class DomAnimationEngine {
|
|||||||
this._elementTriggerStates.set(element, lookupRef = {});
|
this._elementTriggerStates.set(element, lookupRef = {});
|
||||||
}
|
}
|
||||||
|
|
||||||
let oldValue = lookupRef.hasOwnProperty(property) ? lookupRef[property] : 'void';
|
let oldValue = lookupRef.hasOwnProperty(property) ? lookupRef[property] : VOID_STATE;
|
||||||
if (oldValue !== value) {
|
if (oldValue !== value) {
|
||||||
|
value = normalizeTriggerValue(value);
|
||||||
let instruction = trigger.matchTransition(oldValue, value);
|
let instruction = trigger.matchTransition(oldValue, value);
|
||||||
if (!instruction) {
|
if (!instruction) {
|
||||||
// we do this to make sure we always have an animation player so
|
// we do this to make sure we always have an animation player so
|
||||||
@ -407,11 +409,11 @@ export class DomAnimationEngine {
|
|||||||
Object.keys(stateDetails).forEach(triggerName => {
|
Object.keys(stateDetails).forEach(triggerName => {
|
||||||
flushAgain = true;
|
flushAgain = true;
|
||||||
const oldValue = stateDetails[triggerName];
|
const oldValue = stateDetails[triggerName];
|
||||||
const instruction = this._triggers[triggerName].matchTransition(oldValue, 'void');
|
const instruction = this._triggers[triggerName].matchTransition(oldValue, VOID_STATE);
|
||||||
if (instruction) {
|
if (instruction) {
|
||||||
players.push(this.animateTransition(element, instruction));
|
players.push(this.animateTransition(element, instruction));
|
||||||
} else {
|
} else {
|
||||||
const event = makeAnimationEvent(element, triggerName, oldValue, 'void', '', 0);
|
const event = makeAnimationEvent(element, triggerName, oldValue, VOID_STATE, '', 0);
|
||||||
const player = new NoopAnimationPlayer();
|
const player = new NoopAnimationPlayer();
|
||||||
this._queuePlayer(element, triggerName, player, event);
|
this._queuePlayer(element, triggerName, player, event);
|
||||||
}
|
}
|
||||||
@ -515,3 +517,12 @@ function makeAnimationEvent(
|
|||||||
totalTime: number): AnimationEvent {
|
totalTime: number): AnimationEvent {
|
||||||
return <AnimationEvent>{element, triggerName, fromState, toState, phaseName, totalTime};
|
return <AnimationEvent>{element, triggerName, fromState, toState, phaseName, totalTime};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeTriggerValue(value: any): string {
|
||||||
|
switch (typeof value) {
|
||||||
|
case 'boolean':
|
||||||
|
return value ? '1' : '0';
|
||||||
|
default:
|
||||||
|
return value ? value.toString() : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -147,6 +147,46 @@ export function main() {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should stringify boolean triggers to `1` and `0`', () => {
|
||||||
|
@Component({
|
||||||
|
selector: 'if-cmp',
|
||||||
|
template: `
|
||||||
|
<div [@myAnimation]="exp"></div>
|
||||||
|
`,
|
||||||
|
animations: [trigger(
|
||||||
|
'myAnimation',
|
||||||
|
[
|
||||||
|
transition('void => 1', [style({opacity: 0}), animate(1000, style({opacity: 1}))]),
|
||||||
|
transition('1 => 0', [style({opacity: 1}), animate(1000, style({opacity: 0}))])
|
||||||
|
])]
|
||||||
|
})
|
||||||
|
class Cmp {
|
||||||
|
exp: any = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [Cmp]});
|
||||||
|
|
||||||
|
const engine = TestBed.get(ɵAnimationEngine);
|
||||||
|
const fixture = TestBed.createComponent(Cmp);
|
||||||
|
const cmp = fixture.componentInstance;
|
||||||
|
|
||||||
|
cmp.exp = true;
|
||||||
|
fixture.detectChanges();
|
||||||
|
engine.flush();
|
||||||
|
|
||||||
|
expect(getLog().pop().keyframes).toEqual([
|
||||||
|
{offset: 0, opacity: '0'}, {offset: 1, opacity: '1'}
|
||||||
|
]);
|
||||||
|
|
||||||
|
cmp.exp = false;
|
||||||
|
fixture.detectChanges();
|
||||||
|
engine.flush();
|
||||||
|
|
||||||
|
expect(getLog().pop().keyframes).toEqual([
|
||||||
|
{offset: 0, opacity: '1'}, {offset: 1, opacity: '0'}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it('should not throw an error if a trigger with the same name exists in separate components',
|
it('should not throw an error if a trigger with the same name exists in separate components',
|
||||||
() => {
|
() => {
|
||||||
@Component({selector: 'cmp1', template: '...', animations: [trigger('trig', [])]})
|
@Component({selector: 'cmp1', template: '...', animations: [trigger('trig', [])]})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user