I have a list of items that are being updated asynchronously from an Observable
. I have them displaying properly, and I am trying to add a simple animation that fades items in when they are added and fades them out when they are removed. My attempt:
@Component({
selector: 'locker',
template: `
<div *ngFor="let item of (items$ | async)?.items | mapToIterable;trackBy:item?.key"
[@appear]="'show'">
<div *ngIf="item.val">
{{item.key}}
</div>
</div>
`,
animations: [
trigger('appear', [
state('show', style({opacity: 1})),
transition(':enter', [
style({opacity: 0}),
animate(300, style({opacity: 1})),
]),
transition(':leave', [
style({opacity: 1}),
animate(300, style({opacity: 0})),
])
])
],
})
export class LockerComponent {
private items = new BehaviorSubject<any>({
items: {
'axe': 1,
'sword': 1,
'spear': 1,
}
});
items$ = this.items.asObservable();
constructor(private lockerService: LockerService) {
setInterval(() => {
this.items.next({
items: {
'axe': Math.round(Math.random()),
'sword': Math.round(Math.random()),
'spear': Math.round(Math.random()),
}
});
}, 1000);
}
The mapToIterable
pipe was acquired from https://stackoverflow.com/a/35261193/454533
Essentially what this does is randomly update the list of displayed items every couple of seconds.
For the most part this works, and items that are not in the list and added are animated in while items that are in the list and removed are animated out.
The issue is that items that are already in the list are briefly animated out and then back in again. I think that this is caused by items
being updated as a whole, but I am trying to use trackBy
to cover this. It may also have to do with how I am using animations and the animation state.
How can I prevent items that are already in the list from being animated in again?