diff --git a/modules/@angular/compiler-cli/integrationtest/src/animate.ts b/modules/@angular/compiler-cli/integrationtest/src/animate.ts
index 2044716dd1..e171b5bf61 100644
--- a/modules/@angular/compiler-cli/integrationtest/src/animate.ts
+++ b/modules/@angular/compiler-cli/integrationtest/src/animate.ts
@@ -1,19 +1,21 @@
-import {Component, trigger, state, animate, transition, style} from '@angular/core';
+import {AUTO_STYLE, Component, trigger, state, animate, transition, style} from '@angular/core';
@Component({
selector: "animate-cmp",
animations: [
trigger('openClose', [
+ state("*", style({ height: AUTO_STYLE, color: 'black', borderColor: 'black' })),
state('closed, void',
style({ height:"0px", color: "maroon", borderColor: "maroon" })),
state('open',
- style({ height:"*", borderColor:"green", color:"green" })),
+ style({ height: AUTO_STYLE, borderColor:"green", color:"green" })),
transition("* => *", animate(500))
])
],
template: `
+
Look at this box
@@ -25,6 +27,9 @@ export class AnimateCmp {
constructor() {
this.setAsClosed();
}
+ setAsSomethingElse() {
+ this.stateExpression = 'something';
+ }
setAsOpen() {
this.stateExpression = 'open';
}
diff --git a/modules/@angular/compiler-cli/integrationtest/test/animate_spec.ts b/modules/@angular/compiler-cli/integrationtest/test/animate_spec.ts
index 8c2f8ed1ca..dca2e41e37 100644
--- a/modules/@angular/compiler-cli/integrationtest/test/animate_spec.ts
+++ b/modules/@angular/compiler-cli/integrationtest/test/animate_spec.ts
@@ -8,15 +8,19 @@ import {AUTO_STYLE, ReflectiveInjector, DebugElement, getDebugNode} from '@angul
import {browserPlatform, BROWSER_APP_PROVIDERS} from '@angular/platform-browser';
describe("template codegen output", () => {
+ function findTargetElement(elm: DebugElement): DebugElement {
+ // the open-close-container is a child of the main container
+ // if the template changes then please update the location below
+ return elm.children[4];
+ }
+
it("should apply the animate states to the element", (done) => {
const appInjector = ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS,
browserPlatform().injector);
var comp = AnimateCmpNgFactory.create(appInjector);
var debugElement =
getDebugNode(comp.location.nativeElement);
- // the open-close-container is a child of the main container
- // if the template changes then please update the location below
- var targetDebugElement = debugElement.children[3];
+ var targetDebugElement = findTargetElement(debugElement);
comp.instance.setAsOpen();
comp.changeDetectorRef.detectChanges();
@@ -37,4 +41,32 @@ describe("template codegen output", () => {
}, 0);
}, 0);
});
+
+ it("should apply the default animate state to the element", (done) => {
+ const appInjector = ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS,
+ browserPlatform().injector);
+ var comp = AnimateCmpNgFactory.create(appInjector);
+ var debugElement = getDebugNode(comp.location.nativeElement);
+
+ var targetDebugElement = findTargetElement(debugElement);
+
+ comp.instance.setAsSomethingElse();
+ comp.changeDetectorRef.detectChanges();
+
+ setTimeout(() => {
+ expect(targetDebugElement.styles['height']).toEqual(AUTO_STYLE);
+ expect(targetDebugElement.styles['borderColor']).toEqual('black');
+ expect(targetDebugElement.styles['color']).toEqual('black');
+
+ comp.instance.setAsClosed();
+ comp.changeDetectorRef.detectChanges();
+
+ setTimeout(() => {
+ expect(targetDebugElement.styles['height']).not.toEqual(AUTO_STYLE);
+ expect(targetDebugElement.styles['borderColor']).not.toEqual('grey');
+ expect(targetDebugElement.styles['color']).not.toEqual('grey');
+ done();
+ }, 0);
+ }, 0);
+ });
});
diff --git a/modules/@angular/compiler/core_private.ts b/modules/@angular/compiler/core_private.ts
index 388b313161..e2c57ae7ad 100644
--- a/modules/@angular/compiler/core_private.ts
+++ b/modules/@angular/compiler/core_private.ts
@@ -77,6 +77,7 @@ export var AnimationKeyframe: typeof t.AnimationKeyframe = r.AnimationKeyframe;
export type AnimationStyles = t.AnimationStyles;
export var AnimationStyles: typeof t.AnimationStyles = r.AnimationStyles;
export var ANY_STATE = r.ANY_STATE;
+export var DEFAULT_STATE = r.DEFAULT_STATE;
export var EMPTY_STATE = r.EMPTY_STATE;
export var FILL_STYLE_FLAG = r.FILL_STYLE_FLAG;
export var balanceAnimationStyles: typeof t.balanceAnimationStyles = r.balanceAnimationStyles;
diff --git a/modules/@angular/compiler/src/animation/animation_compiler.ts b/modules/@angular/compiler/src/animation/animation_compiler.ts
index c75900a15f..e1d23badaf 100644
--- a/modules/@angular/compiler/src/animation/animation_compiler.ts
+++ b/modules/@angular/compiler/src/animation/animation_compiler.ts
@@ -6,7 +6,7 @@ import {Identifiers} from '../identifiers';
import * as o from '../output/output_ast';
import {AUTO_STYLE} from '@angular/core';
-import {ANY_STATE, EMPTY_STATE} from '../../core_private';
+import {DEFAULT_STATE, ANY_STATE, EMPTY_STATE} from '../../core_private';
import {
AnimationParseError,
@@ -64,6 +64,7 @@ export class AnimationCompiler {
}
var _ANIMATION_FACTORY_ELEMENT_VAR = o.variable('element');
+var _ANIMATION_DEFAULT_STATE_VAR = o.variable('defaultStateStyles');
var _ANIMATION_FACTORY_VIEW_VAR = o.variable('view');
var _ANIMATION_FACTORY_RENDERER_VAR = _ANIMATION_FACTORY_VIEW_VAR.prop('renderer');
var _ANIMATION_CURRENT_STATE_VAR = o.variable('currentState');
@@ -212,6 +213,9 @@ class _AnimationBuilder implements AnimationAstVisitor {
//visit each of the declarations first to build the context state map
ast.stateDeclarations.forEach(def => def.visit(this, context));
+ //this should always be defined even if the user overrides it
+ context.stateMap.registerState(DEFAULT_STATE, {});
+
var statements = [];
statements.push(
_ANIMATION_FACTORY_VIEW_VAR.callMethod('cancelActiveAnimation', [
@@ -223,6 +227,11 @@ class _AnimationBuilder implements AnimationAstVisitor {
statements.push(_ANIMATION_COLLECTED_STYLES.set(EMPTY_MAP).toDeclStmt());
statements.push(_ANIMATION_PLAYER_VAR.set(o.NULL_EXPR).toDeclStmt());
+ statements.push(
+ _ANIMATION_DEFAULT_STATE_VAR.set(
+ this._statesMapVar.key(o.literal(DEFAULT_STATE))
+ ).toDeclStmt());
+
statements.push(
_ANIMATION_START_STATE_STYLES_VAR.set(
this._statesMapVar.key(_ANIMATION_CURRENT_STATE_VAR)
@@ -230,7 +239,7 @@ class _AnimationBuilder implements AnimationAstVisitor {
statements.push(
new o.IfStmt(_ANIMATION_START_STATE_STYLES_VAR.equals(o.NULL_EXPR), [
- _ANIMATION_START_STATE_STYLES_VAR.set(EMPTY_MAP).toStmt()
+ _ANIMATION_START_STATE_STYLES_VAR.set(_ANIMATION_DEFAULT_STATE_VAR).toStmt()
]));
statements.push(
@@ -240,7 +249,7 @@ class _AnimationBuilder implements AnimationAstVisitor {
statements.push(
new o.IfStmt(_ANIMATION_END_STATE_STYLES_VAR.equals(o.NULL_EXPR), [
- _ANIMATION_END_STATE_STYLES_VAR.set(EMPTY_MAP).toStmt()
+ _ANIMATION_END_STATE_STYLES_VAR.set(_ANIMATION_DEFAULT_STATE_VAR).toStmt()
]));
diff --git a/modules/@angular/core/private_export.ts b/modules/@angular/core/private_export.ts
index 77906c4817..b331a22798 100644
--- a/modules/@angular/core/private_export.ts
+++ b/modules/@angular/core/private_export.ts
@@ -39,6 +39,7 @@ import {AnimationStyles as AnimationStyles_} from './src/animation/animation_sty
import * as animationUtils from './src/animation/animation_style_util';
import {
ANY_STATE as ANY_STATE_,
+ DEFAULT_STATE as DEFAULT_STATE_,
EMPTY_STATE as EMPTY_STATE_,
FILL_STYLE_FLAG as FILL_STYLE_FLAG_
} from './src/animation/animation_constants';
@@ -130,6 +131,7 @@ export declare namespace __core_private_types__ {
export type AnimationStyles = AnimationStyles_;
export var AnimationStyles: typeof AnimationStyles_;
export var ANY_STATE: typeof ANY_STATE_;
+ export var DEFAULT_STATE: typeof DEFAULT_STATE_;
export var EMPTY_STATE: typeof EMPTY_STATE_;
export var FILL_STYLE_FLAG: typeof FILL_STYLE_FLAG_;
}
@@ -199,6 +201,7 @@ export var __core_private__ = {
collectAndResolveStyles: animationUtils.collectAndResolveStyles,
AnimationStyles: AnimationStyles_,
ANY_STATE: ANY_STATE_,
+ DEFAULT_STATE: DEFAULT_STATE_,
EMPTY_STATE: EMPTY_STATE_,
FILL_STYLE_FLAG: FILL_STYLE_FLAG_
};
diff --git a/modules/@angular/core/src/animation/animation_constants.ts b/modules/@angular/core/src/animation/animation_constants.ts
index 9a6a330d54..236e86afd0 100644
--- a/modules/@angular/core/src/animation/animation_constants.ts
+++ b/modules/@angular/core/src/animation/animation_constants.ts
@@ -1,3 +1,4 @@
export const FILL_STYLE_FLAG = 'true'; // TODO (matsko): change to boolean
export const ANY_STATE = '*';
+export const DEFAULT_STATE = '*';
export const EMPTY_STATE = 'void';
diff --git a/modules/@angular/core/src/animation/metadata.ts b/modules/@angular/core/src/animation/metadata.ts
index 577d1138b2..a1148cc4e7 100644
--- a/modules/@angular/core/src/animation/metadata.ts
+++ b/modules/@angular/core/src/animation/metadata.ts
@@ -292,6 +292,10 @@ export function style(tokens: string|{[key: string]: string | number}|Array {
+ makeAnimationCmp(tcb, '', [
+ trigger('status', [
+ state(DEFAULT_STATE, style({ "background": 'grey' })),
+ state('green', style({ "background": 'green' })),
+ state('red', style({ "background": 'red' })),
+ transition('* => *', [ animate(1000) ])
+ ])
+ ], (fixture) => {
+ tick();
+
+ var cmp = fixture.debugElement.componentInstance;
+ var node = getDOM().querySelector(fixture.debugElement.nativeElement, '.target');
+ cmp.exp = 'green';
+ fixture.detectChanges();
+ flushMicrotasks();
+
+ var animation = driver.log.pop();
+ var keyframes = animation['keyframeLookup'];
+ expect(keyframes[1]).toEqual([1, {'background': 'green' }]);
+
+ cmp.exp = 'blue';
+ fixture.detectChanges();
+ flushMicrotasks();
+
+ animation = driver.log.pop();
+ keyframes = animation['keyframeLookup'];
+ expect(keyframes[0]).toEqual([0, {'background': 'green' }]);
+ expect(keyframes[1]).toEqual([1, {'background': 'grey' }]);
+
+ cmp.exp = 'red';
+ fixture.detectChanges();
+ flushMicrotasks();
+
+ animation = driver.log.pop();
+ keyframes = animation['keyframeLookup'];
+ expect(keyframes[0]).toEqual([0, {'background': 'grey' }]);
+ expect(keyframes[1]).toEqual([1, {'background': 'red' }]);
+
+ cmp.exp = 'orange';
+ fixture.detectChanges();
+ flushMicrotasks();
+
+ animation = driver.log.pop();
+ keyframes = animation['keyframeLookup'];
+ expect(keyframes[0]).toEqual([0, {'background': 'red' }]);
+ expect(keyframes[1]).toEqual([1, {'background': 'grey' }]);
+ });
+ })));
+
it('should seed in the origin animation state styles into the first animation step',
inject([TestComponentBuilder, AnimationDriver], fakeAsync((tcb: TestComponentBuilder, driver: MockAnimationDriver) => {
makeAnimationCmp(tcb, '', [
diff --git a/modules/playground/src/animate/app/animate-app.ts b/modules/playground/src/animate/app/animate-app.ts
index 871bda9dd4..604de904c4 100644
--- a/modules/playground/src/animate/app/animate-app.ts
+++ b/modules/playground/src/animate/app/animate-app.ts
@@ -17,7 +17,9 @@ import {
+ |
+
@@ -34,6 +36,7 @@ import {
])
]),
trigger("boxAnimation", [
+ state("*", style({ "height": "*", "background-color": "#dddddd", "color":"black" })),
state("void, hidden", style({ "height": 0, "opacity": 0 })),
state("start", style({ "background-color": "red", "height": "*" })),
state("active", style({ "background-color": "orange", "color": "white", "font-size":"100px" })),
@@ -65,15 +68,15 @@ export class AnimateApp {
get state() { return this._state; }
set state(s) {
this._state = s;
- if (s == 'start' || s == 'active') {
+ if (s == 'void') {
+ this.items = [];
+ } else {
this.items = [
1,2,3,4,5,
6,7,8,9,10,
11,12,13,14,15,
16,17,18,19,20
];
- } else {
- this.items = [];
}
}
}