Jeanluca Scaljeri
Jeanluca Scaljeri

Reputation: 29199

Staggering animation in Angular not working if item is replaced instead of added/removed

After a bit of a struggle I finally have staggering animations working

DEMO (The code was originally copied from here)

The relevant animation code is

   trigger('cardAnimation', [
  // Transition from any state to any state
  transition('* => *', [
    // Initially the all cards are not visible
    query(':enter', style({ opacity: 0 }), { optional: true }),

    // Each card will appear sequentially with the delay of 300ms
    query(
      ':enter',
      stagger('300ms', [
        animate(
          '.5s ease-in',
          keyframes([
            style({ opacity: 0, transform: 'translateY(-50%)', offset: 0 }),
            style({
              opacity: 0.5,
              transform: 'translateY(-10px) scale(1.1)',
              offset: 0.3,
            }),
            style({ opacity: 1, transform: 'translateY(0)', offset: 1 }),
          ])
        ),
      ]),
      { optional: true }
    ),

    // Cards will disappear sequentially with the delay of 300ms
    query(
      ':leave',
      stagger('300ms', [
        animate(
          '500ms ease-out',
          keyframes([
            style({ opacity: 1, transform: 'scale(1.1)', offset: 0 }),
            style({ opacity: 0.5, transform: 'scale(.5)', offset: 0.3 }),
            style({ opacity: 0, transform: 'scale(0)', offset: 1 }),
          ])
        ),
      ]),
      { optional: true }
    ),
  ]),
]),

As you can see in the demo, adding and removing is animated. What I don't understand is, that this same logic (removing/adding) is not applied when I replace a card item in the list. I would expect that both the :leave and then the :enter would trigger.

Any suggestion what I missed in my animation?

Upvotes: 0

Views: 130

Answers (1)

derstauner
derstauner

Reputation: 1806

Of course it doesn't work. The animation is triggered, if the length of the array changes. But clicking on the replace button updates only a specific element.

Change the onReplace function like this:

this.cards.splice(index, 1);
setTimeout(() => this.cards.splice(index, 0, `Card ${++this.index}`));

The setTimeout is needed, because deleting and inserting has to be done in a separate execution context, in order to let angular detect the change in the array size.

Upvotes: 1

Related Questions