feat(animations): provide aliases for :enter and :leave transitions (#11991)

This commit is contained in:
Matias Niemelä 2016-09-30 17:15:56 +01:00 committed by Chuck Jazdzewski
parent df1822fc2a
commit e884f4854d
2 changed files with 98 additions and 1 deletions

View File

@ -132,9 +132,25 @@ function _parseAnimationStateTransition(
return new AnimationStateTransitionAst(transitionExprs, stepsAst);
}
function _parseAnimationAlias(alias: string, errors: AnimationParseError[]): string {
switch (alias) {
case ':enter':
return 'void => *';
case ':leave':
return '* => void';
default:
errors.push(
new AnimationParseError(`the transition alias value "${alias}" is not supported`));
return '* => *';
}
}
function _parseAnimationTransitionExpr(
eventStr: string, errors: AnimationParseError[]): AnimationStateTransitionExpression[] {
var expressions: any[] /** TODO #9100 */ = [];
var expressions: AnimationStateTransitionExpression[] = [];
if (eventStr[0] == ':') {
eventStr = _parseAnimationAlias(eventStr, errors);
}
var match = eventStr.match(/^(\*|[-\w]+)\s*(<?[=-]>)\s*(\*|[-\w]+)$/);
if (!isPresent(match) || match.length < 4) {
errors.push(new AnimationParseError(`the provided ${eventStr} is not of a supported format`));

View File

@ -146,6 +146,87 @@ function declareTests({useJit}: {useJit: boolean}) {
expect(kf[1]).toEqual([1, {'background': 'blue'}]);
}));
describe('animation aliases', () => {
it('should animate the ":enter" animation alias as "void => *"', fakeAsync(() => {
TestBed.overrideComponent(DummyIfCmp, {
set: {
template: `
<div *ngIf="exp" [@myAnimation]="exp"></div>
`,
animations: [trigger(
'myAnimation',
[transition(
':enter',
[style({'opacity': 0}), animate('500ms', style({opacity: 1}))])])]
}
});
const driver = TestBed.get(AnimationDriver) as MockAnimationDriver;
let fixture = TestBed.createComponent(DummyIfCmp);
var cmp = fixture.componentInstance;
cmp.exp = true;
fixture.detectChanges();
expect(driver.log.length).toEqual(1);
var animation = driver.log[0];
expect(animation['duration']).toEqual(500);
}));
it('should animate the ":leave" animation alias as "* => void"', fakeAsync(() => {
TestBed.overrideComponent(DummyIfCmp, {
set: {
template: `
<div *ngIf="exp" [@myAnimation]="exp"></div>
`,
animations: [trigger(
'myAnimation',
[transition(':leave', [animate('999ms', style({opacity: 0}))])])]
}
});
const driver = TestBed.get(AnimationDriver) as MockAnimationDriver;
let fixture = TestBed.createComponent(DummyIfCmp);
var cmp = fixture.componentInstance;
cmp.exp = true;
fixture.detectChanges();
expect(driver.log.length).toEqual(0);
cmp.exp = false;
fixture.detectChanges();
expect(driver.log.length).toEqual(1);
var animation = driver.log[0];
expect(animation['duration']).toEqual(999);
}));
it('should throw an error when an unsupported alias is detected which is prefixed a colon value',
fakeAsync(() => {
TestBed.overrideComponent(DummyIfCmp, {
set: {
template: `
<div *ngIf="exp" [@myAnimation]="exp"></div>
`,
animations: [trigger(
'myAnimation',
[transition(':dont_leave_me', [animate('444ms', style({opacity: 0}))])])]
}
});
var message = '';
try {
let fixture = TestBed.createComponent(DummyIfCmp);
} catch (e) {
message = e.message;
}
expect(message).toMatch(
/the transition alias value ":dont_leave_me" is not supported/);
}));
});
it('should animate between * and void and back even when no expression is assigned',
fakeAsync(() => {
TestBed.overrideComponent(DummyIfCmp, {