Search code examples
javascriptangulartypescriptangular-animations

How can I apply animations to a list of elements one by one with angular 4 animation?


I'm trying to apply angular 4 animation to list of html elements like

facilities = ['<p> <span class="glyphicon glyphicon-hand-right"> </span> Text 1</p>',
        '<p> <span class="glyphicon glyphicon-hand-right"></span>Text 2</p>',
        '<p> <span class="glyphicon glyphicon-hand-right"></span> Text 3</p>',
        '<p> <span class="glyphicon glyphicon-hand-right"></span> Text 4</p>',
];

one by one with below code:

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%)'}))
    ])
  ])
]

When I put this trigger to list elements, all the elements come on the screen all in one go. I want to make them appear one by one, like fetch text 1 and then text 2 on html. How can I do that?


Solution

  • UPDATE: Using staggers:

    HTML:

    <ul [@listAnimation]="items.length">
           <li *ngFor="let item of items" >
              <div [innerHTML]="item"></div>
           </li>
    </ul>
    

    Typescript:

    ....
    animations: [
        trigger('listAnimation', [
       transition('* => *', [
    
         query(':leave', [
          stagger(500, [
            animate(1000, style({ opacity: 0 }))
          ])
        ], { optional: true }),
         query(':enter', [
               style({ opacity: 0 }),
     stagger(500, [
            animate(1000, style({ opacity: 1 }))
          ])
        ], { optional: true })
      ])
    ...
    

    DEMO


    It can be done with Angular animation callbacks and with some help written in typescript

    HTML:

     <ul>
        <li *ngFor="let item of listCopy;" (@flyInOut.done)="getNextItem()" [@flyInOut]="'in'" >
         <ul>
            <li *ngFor="let item of list" (@flyInOut.done)="getNextItem()" [@flyInOut]="'in'" >
               <div [innerHTML]="item"></div>
            </li>
         </ul>        
       </li>
     </ul>
    

    Typescript:

       .....
       @Component({
       ....
       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%)'}))
            ])
          ])
        ]
        ....
        list = ['Item1', 'Item2', 'Item3', 'Item4'];
        listCopy = []; 
        next: number = 0;
    
        constructor(){
            this.getNextItem();
        }
    
        getNextItem() {
            if(this.next < this.list.length) {
              this.listCopy.push(this.list[this.next++]);
            }
        }
    

    Plunker (I put 1000ms to emphasise the animation)