Skip to content

Commit

Permalink
fix(animations): make sure @.disabled works in non-animation components
Browse files Browse the repository at this point in the history
Note 4.3 only!

Prior to this fix when [@.disabled] was used in a component that
contained zero animation code it wouldn't register properly because the
renderer associated with that component was not an animation renderer.
This patch ensures that it gets registered even when there are no
animations set.
  • Loading branch information
matsko authored and alxhub committed Jul 19, 2017
1 parent 4c1f32b commit a5c4bb5
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 20 deletions.
25 changes: 11 additions & 14 deletions packages/animations/browser/src/render/animation_engine_next.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
51 changes: 51 additions & 0 deletions packages/core/test/animation/animation_integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2281,6 +2281,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: `
<div [@.disabled]="disableExp">
<child-cmp #child></child-cmp>
</div>
`
})
class ParentCmp {
@ViewChild('child') public child: ChildCmp|null = null;
disableExp = false;
}

@Component({
selector: 'child-cmp',
template: `
<div [@myAnimation]="exp"></div>
`,
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);
});
});
});

Expand Down
28 changes: 22 additions & 6 deletions packages/platform-browser/animations/src/animation_renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -174,14 +177,22 @@ 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); }

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 {
Expand All @@ -193,21 +204,26 @@ 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);
}
}

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 => {
Expand Down

0 comments on commit a5c4bb5

Please sign in to comment.