10

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

2
  • You can come up with plunker if would be nice to help you. Commented Jul 19, 2016 at 17:42
  • I've edited my post with a plnkr Commented Jul 19, 2016 at 19:06

3 Answers 3

10

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 :)

Sign up to request clarification or add additional context in comments.

2 Comments

Marking correct as the answer is 'you can't YET'. Thanks for the link to the feature request. At least now I can start working around the issue instead of attempting to find an undocumented feature.
Yep, 'you can't YET' this is the answer. I wanted to give more details on why so people can understand. As for workaround, you might be able to use some CSS but it will be limited. Working around this is hard since angular stores all the animation sequences and data inside a generated AppView class that is internal and you can't access it...
3

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!

Comments

0

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();
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.