I have a component that fetches list of items from server and then display that list using *ngFor in template.
I want the list to be displayed with some animation, but one after other. I mean each list item should animate in after other.
I am trying something like this:
import { Component, Input, trigger, state, animate, transition, style } from '@angular/core'; @Component({ selector: 'list-item', template: ` <li @flyInOut="'in'">{{item}}</li>`, animations: [ trigger('flyInOut', [ state('in', style({ transform: 'translateX(0)' })), transition('void => *', [ style({ transform: 'translateX(-100%)' }), animate(100) ]), transition('* => void', [ animate(100, style({ transform: 'translateX(100%)' })) ]) ]) ] }) export class ListItemComponent { @Input() item: any; }
and in my list component template I am using it like:
<ul> <li *ngFor="let item of list;"> <list-item [item]="item"></list-item> </li> </ul>
What it does is displays whole list at once. I want items to enter one by one with some animation.
The keyframes() function in Angular allows you to specify multiple interim styles within a single transition.
However, we can use the style function within transitions and animations to define both the initial styling and also the final one, after the animation has been performed. To use this trigger from our component template we just need to attach it to a component that might get removed or added to the DOM.
Transitions between two states take place so that we can build simple animations between two states driven by a model attribute. Transition basically means navigating from the current state to a new state. In angular, the transition is an animation-specific function which is used in angular's animation DSL language.
I couldn't find stagger
support on ngFor
in the documentation, but there's now animation.done
events
, which can be used to make staggering ngFor
StackBlitz
@Component({ selector: 'my-app', template: ` <ul> <li *ngFor="let hero of staggeringHeroes; let i = index" (@flyInOut.done)="doNext()" [@flyInOut]="'in'" (click)="removeMe(i)"> {{hero}} </li> </ul> `, animations: [ trigger('flyInOut', [ state('in', style({transform: 'translateX(0)'})), transition('void => *', [ animate(300, keyframes([ style({opacity: 0, transform: 'translateX(-100%)', offset: 0}), style({opacity: 1, transform: 'translateX(15px)', offset: 0.3}), style({opacity: 1, transform: 'translateX(0)', offset: 1.0}) ])) ]), transition('* => void', [ animate(300, keyframes([ style({opacity: 1, transform: 'translateX(0)', offset: 0}), style({opacity: 1, transform: 'translateX(-15px)', offset: 0.7}), style({opacity: 0, transform: 'translateX(100%)', offset: 1.0}) ])) ]) ]) ] }) export class App { heroes: any[] = ['Alpha', 'Bravo', 'Charlie', 'Delta', 'Echo', 'Foxtrot', 'Golf', 'Hotel', 'India']; next: number = 0; staggeringHeroes: any[] = []; constructor(){ this.doNext(); } doNext() { if(this.next < this.heroes.length) { this.staggeringHeroes.push(this.heroes[this.next++]); } } removeMe(i) { this.staggeringHeroes.splice(i, 1); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With