Before I go on, I should note I posted a similar question earlier, with a similar content to this one, BUT I thougth that the source of the bug was using a custom-component inside an ngFor loop. I have seen that is not the issue, so I have deleted the original question to make my query more accurate and to not mislead anyone.
I am currently working on a project using Ionic 5 and Angular 9 where we have to use lotties in certain views. I am using the ngx-lottie library (https://github.com/ngx-lottie/ngx-lottie#api) and for my purposes, instead of inserting the lottie within the template in each view as the library's API shows, I have built a component to be included within other views. The code for said component is as follows:
import { Component, OnInit, OnChanges, SimpleChanges, Input } from '@angular/core';
import { AnimationItem } from 'lottie-web';
import { AnimationOptions } from 'ngx-lottie';
@Component({
selector: 'app-lottie-player',
template: `<ng-lottie
[options]="options"
[styles]="styles"
(animationCreated)="animationCreated($event)">
</ng-lottie>`,
})
export class LottiePlayerComponent implements OnInit, OnChanges {
@Input() lottieToPlay: string; // Route to the json within assets/lotties
@Input() lottieToUpdate: string; // Secondary json in case a switch is needed
@Input() animationDirection: number; // 1 for normal direction, -1 for reversed animation
@Input() dimensions: any; // Layout specifications passed from parent component
options: AnimationOptions = {
path: '',
};
styles: Partial<CSSStyleDeclaration> = {
margin: '0 auto',
};
private animationItem: AnimationItem;
constructor() { }
ngOnInit() {
this.updateAnimation();
}
ngOnChanges(changes: SimpleChanges) {
const directionChange = changes.animationDirection;
if (directionChange && !directionChange.firstChange) {
this.playAnimation(this.animationItem, directionChange.currentValue);
}
}
updateAnimation(): void {
this.options = {
...this.options,
path: this.lottieToPlay,
};
this.styles = {
...this.styles,
...this.dimensions
};
}
animationCreated(animationItem: AnimationItem): void {
this.animationItem = animationItem;
this.animationItem.autoplay = false;
this.animationItem.loop = false;
}
playAnimation(animationItem: AnimationItem, direction?: number): void {
this.animationItem = animationItem;
this.animationItem.setDirection(Math.sign(direction) === 1 ? 1 : -1);
this.animationItem.play();
}
}
The component esentially does the following:
- Receives the json to render from whichever parent component was inserted on.
- Receives custom css properties and the direction that the lottie will play in from said parent.
- Starts the lottie in a 'paused' state, to trigger the animation on click.
So when I insert it in a view like this:
<ion-buttons slot="secondary">
<ion-button class="icon-container" (click)="changeIconAndNavigate()">
<app-lottie-player
[dimensions]="lottieClassSpecs"
[lottieToPlay]="lottieFav"
[animationDirection]="lottieAnimDirection">
</app-lottie-player>
</ion-button>
</ion-buttons>
Inside a parent component that has a method like this one:
public changeIconAndNavigate() {
this.lottieAnimDirection = 1;
}
The lottie works as intended. The animation triggers just once and stays in its finished animation state.
The problem arises when I insert the lottie as above, but making several insertions in the same component instead of a single one. I believe now that the cause of the issue might be that I built the original component wrong, so to speak. In another component, I have inserted the lottie-player like this:
<ion-item *ngFor="let card of cards" class="card-info">
...
<ion-item lines="full">
<span class="card-span">{{ card.title }}</span>
<ion-button class="lottie-holder" (click)="toggleSingleSubscription(card)">
<app-lottie-player
[dimensions]="lottieClassSpecs"
[lottieToPlay]="lottieAdd"
[animationDirection]="lottieAnimDirection">
</app-lottie-player>
</ion-button>
</ion-item>
...
</ion-item>
Just to be sure, I inserted another instance of the lottie-player outside the ngFor loop, to see how it would react. The entire parent component that controls these cards simply inserts them or pops them into an array, and each time, after the insertion, I change the this.lottieANimDirection to 1 or -1 as required, so that the ngOnChanges within the lottie component can pick up the change and render the animation accordingly
And what I expected to see was each lottie animating individually- but all of them do. So if I click on the bottom one, where it says 'subscribe'...
The lottie above animates as well.
Not only the one in the card above, but also the for-testing-purposes <app-lottie-player> I tried inserting above the ngFor loop also animated. I beleve the cause of the bug might be that, because of how I built this basic component, instead of creating one instance of the player within the controller, it is re-updating the same single instance, causing the information received to display in all insertions in the DOM because they would all actually come from one single instance. But I am clueless about how to solve it.
If anyone has the slightest idea about why this bug in the lotties might be happening, I'm all ears/eyes.


toggleSingleSubscription(card)'s code look like? You should show your parent code as well. It sounds to me that you are passing every card the same lottie inputs, based on your for loop. You may want to make a card component and each one can manage its own lottie inputs and their state. - cjd82187toggleSingleSubscription()checks if the id of the card is in the array, inserts it if it isn't and pops it if its not, and then updates this.lottieAnimDirection. At first I suspected that what you are suggesting (the ngLoop essentially giving the same lottie inputs to everyone) was the cause. But then it wouldn't make sense for the lottie OUTSIDE of the ngFor to animate as well - JurgenBlitzthis. lottieANimDirectionin your parent component, and its passing that value to everything in its template - cjd82187