diff --git a/packages/animations/browser/src/render/animation_engine_next.ts b/packages/animations/browser/src/render/animation_engine_next.ts
index 7f1fef4b03..4aa25fc0db 100644
--- a/packages/animations/browser/src/render/animation_engine_next.ts
+++ b/packages/animations/browser/src/render/animation_engine_next.ts
@@ -67,20 +67,17 @@ export class AnimationEngine {
this._transitionEngine.removeNode(namespaceId, element, context);
}
- process(namespaceId: string, element: any, property: string, value: any): boolean {
- switch (property.charAt(0)) {
- case '.':
- if (property == '.disabled') {
- this._transitionEngine.markElementAsDisabled(element, !!value);
- }
- return false;
- case '@':
- const [id, action] = parseTimelineCommand(property);
- const args = value as any[];
- this._timelineEngine.command(id, element, action, args);
- return false;
- default:
- return this._transitionEngine.trigger(namespaceId, element, property, value);
+ disableAnimations(element: any, disable: boolean) {
+ this._transitionEngine.markElementAsDisabled(element, disable);
+ }
+
+ process(namespaceId: string, element: any, property: string, value: any) {
+ if (property.charAt(0) == '@') {
+ const [id, action] = parseTimelineCommand(property);
+ const args = value as any[];
+ this._timelineEngine.command(id, element, action, args);
+ } else {
+ this._transitionEngine.trigger(namespaceId, element, property, value);
}
}
diff --git a/packages/core/test/animation/animation_integration_spec.ts b/packages/core/test/animation/animation_integration_spec.ts
index 52acb25d8a..32e779eaed 100644
--- a/packages/core/test/animation/animation_integration_spec.ts
+++ b/packages/core/test/animation/animation_integration_spec.ts
@@ -1815,12 +1815,12 @@ export function main() {
selector: 'my-cmp',
template: `
-
- {{ item }}
+ {{ item }}
`,
@@ -2153,6 +2153,57 @@ export function main() {
expect(cmp.startEvent.totalTime).toEqual(9876);
// the done event isn't fired because it's an actual animation
}));
+
+ it('should work when there are no animations on the component handling the disable/enable flag',
+ () => {
+ @Component({
+ selector: 'parent-cmp',
+ template: `
+
+
+
+ `
+ })
+ class ParentCmp {
+ @ViewChild('child') public child: ChildCmp|null = null;
+ disableExp = false;
+ }
+
+ @Component({
+ selector: 'child-cmp',
+ template: `
+
+ `,
+ animations: [trigger(
+ 'myAnimation',
+ [transition(
+ '* => go, * => goAgain',
+ [style({opacity: 0}), animate('1s', style({opacity: 1}))])])]
+ })
+ class ChildCmp {
+ public exp = '';
+ }
+
+ TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]});
+
+ const fixture = TestBed.createComponent(ParentCmp);
+ const cmp = fixture.componentInstance;
+ cmp.disableExp = true;
+ fixture.detectChanges();
+ resetLog();
+
+ const child = cmp.child !;
+ child.exp = 'go';
+ fixture.detectChanges();
+
+ expect(getLog().length).toEqual(0);
+ resetLog();
+
+ cmp.disableExp = false;
+ child.exp = 'goAgain';
+ fixture.detectChanges();
+ expect(getLog().length).toEqual(1);
+ });
});
});
diff --git a/packages/platform-browser/animations/src/animation_renderer.ts b/packages/platform-browser/animations/src/animation_renderer.ts
index 3f57a5b9ab..4b551a96ec 100644
--- a/packages/platform-browser/animations/src/animation_renderer.ts
+++ b/packages/platform-browser/animations/src/animation_renderer.ts
@@ -9,6 +9,9 @@ import {AnimationTriggerMetadata} from '@angular/animations';
import {ɵAnimationEngine as AnimationEngine} from '@angular/animations/browser';
import {Injectable, NgZone, Renderer2, RendererFactory2, RendererStyleFlags2, RendererType2} from '@angular/core';
+const ANIMATION_PREFIX = '@';
+const DISABLE_ANIMATIONS_FLAG = '@.disabled';
+
@Injectable()
export class AnimationRendererFactory implements RendererFactory2 {
private _currentId: number = 0;
@@ -166,7 +169,11 @@ export class BaseAnimationRenderer implements Renderer2 {
}
setProperty(el: any, name: string, value: any): void {
- this.delegate.setProperty(el, name, value);
+ if (name.charAt(0) == ANIMATION_PREFIX && name == DISABLE_ANIMATIONS_FLAG) {
+ this.disableAnimations(el, !!value);
+ } else {
+ this.delegate.setProperty(el, name, value);
+ }
}
setValue(node: any, value: string): void { this.delegate.setValue(node, value); }
@@ -174,6 +181,10 @@ export class BaseAnimationRenderer implements Renderer2 {
listen(target: any, eventName: string, callback: (event: any) => boolean | void): () => void {
return this.delegate.listen(target, eventName, callback);
}
+
+ protected disableAnimations(element: any, value: boolean) {
+ this.engine.disableAnimations(element, value);
+ }
}
export class AnimationRenderer extends BaseAnimationRenderer implements Renderer2 {
@@ -185,9 +196,12 @@ export class AnimationRenderer extends BaseAnimationRenderer implements Renderer
}
setProperty(el: any, name: string, value: any): void {
- if (name.charAt(0) == '@') {
- name = name.substr(1);
- this.engine.process(this.namespaceId, el, name, value);
+ if (name.charAt(0) == ANIMATION_PREFIX) {
+ if (name.charAt(1) == '.' && name == DISABLE_ANIMATIONS_FLAG) {
+ this.disableAnimations(el, !!value);
+ } else {
+ this.engine.process(this.namespaceId, el, name.substr(1), value);
+ }
} else {
this.delegate.setProperty(el, name, value);
}
@@ -195,11 +209,13 @@ export class AnimationRenderer extends BaseAnimationRenderer implements Renderer
listen(target: 'window'|'document'|'body'|any, eventName: string, callback: (event: any) => any):
() => void {
- if (eventName.charAt(0) == '@') {
+ if (eventName.charAt(0) == ANIMATION_PREFIX) {
const element = resolveElementFromTarget(target);
let name = eventName.substr(1);
let phase = '';
- if (name.charAt(0) != '@') { // transition-specific
+ // @listener.phase is for trigger animation callbacks
+ // @@listener is for animation builder callbacks
+ if (name.charAt(0) != ANIMATION_PREFIX) {
[name, phase] = parseTriggerCallbackName(name);
}
return this.engine.listen(this.namespaceId, element, name, phase, event => {