Using Typescript & Angular 2.0.0-rc.4
How can I specify style property values from the template so that I can re-use buttons? For example, if I wanted to specify a different background-color for each button based on some property that is bound by the template. See below
Assume the following component:
import {
Component,
OnInit,
OnDestroy,
Input,
style,
state,
animate,
transition,
trigger
} from '@angular/core';
@Component({
selector: 'my-toggle-button',
template: `<div @state="state" (click)="click()">{{bgColor}}</div>`,
animations: [
trigger('state', [
state('inactive', style({
'color': '#606060'
})),
state('active', style({
'color': '#fff',
'background-color': '#606060' // I want this to be bgColor
})),
transition('inactive <=> active', animate('100ms ease-out'))
])
]
})
export class ToggleButtonComponent implements OnInit {
@Input() bgColor: string;
state: string = 'inactive';
active: boolean = false;
ngOnInit() {
this.state = this.active ? 'active' : 'inactive';
}
click() {
this.active = !this.active;
this.state = this.active ? 'active' : 'inactive';
}
}
calling template:
<h1>Animated Directive</h1>
<my-toggle-button [bgColor]="'#f00'"></my-toggle-button>
<my-toggle-button [bgColor]="'#0f0'"></my-toggle-button>
<my-toggle-button [bgColor]="'#00f'"></my-toggle-button>
http://plnkr.co/edit/KBO2pgS8B0lSAPLIf0Js?p=preview
Based on the title of this question I assume you want to bind expressions to an animation configuration.
It doesn't really matter if the value comes from an inline template expression or from a property binding on the component class.
In RC4 this is not possible, the animation module/engine supports static/constant definitions. I'm using the term definitions and not styles since such bindings can be used on styles as well as keyframes, transitions, animate and basically all animation metadata factories.
You should expect this feature to come in the one of the next versions of angular, can't tell when but it should come. Setting animations metadata as referenced variables rather then constants is super powerful and basically mandatory as it's the base requirement for re-usable animations.
Having re-usable animation will lead the way for wider community adoption of the animation module.
In angular 1 it was built in since the animation module used globally defined CSS classes to start animations thus CSS classes were used for the re-usable part.
In angular 2 the approach is different due to a lot of reasons (encapsulation, own CSS parser, animation engine not tied to CSS and more...)
re-usable animation will pave the path for complete 3rd party libraries for animations, think animation.css or ng-fx but as a set of angular directives/modules.
I have opened an issue on the angular repo, about 3 weeks ago, requesting this feature. The lead dev on the animation has confirmed it's coming so hold tight :)
As of today you can achieve what you want!
You can use automatic property calculation!
In your css or template set background-color to the final color.
<div @state="state" [style.background-color]="bgColor" (click)="click()">{{bgColor}}</div>
In your animation definition :
animations: [
trigger('state', [
state('inactive', style({
'color': '#606060',
'background-color' : 'transparent'
})),
state('active', style({
'color': '#fff',
'background-color': '*' // <====
})),
transition('inactive <=> active', animate('100ms ease-out'))
])
]
something like this should work!
It is totally possible to do it since Angular v4.2.
You can find details in the article "A New Wave of Animation Features in Angular". See section #8.
Here is a code sample from it:
import {AnimationBuilder, AnimationPlayer} from "@angular/animations";
@Component({
selector: 'loader',
template: `
<div class="loading-stage">
<div class="loading-bar" #loadingBar>
{{ percentage }}%
</div>
</div>
`
})
export class LoaderComponent {
@ViewChild('loadingBar')
public loadingBar;
public player: AnimationPlayer;
private _percentage = 0;
constructor(private _builder: AnimationBuilder) {}
get percentage() { return this._percentage; }
@Input('percentage')
set percentage(p: number) {
this._percentage = p;
if (this.player) {
this.player.destroy();
}
const factory = this._builder.build([
style({ width: '*' }),
animate('350ms cubic-bezier(.35, 0, .25, 1)', style({ width: (p * 100) + '%' }))
]);
this.player = factory.create(this.loadingBar.nativeElement, {});
this.player.play();
}
}