I am trying to animate the change of items in a list in angular. The animation should be a simpel fade-in-out. This works absolutely fine for individual items getting inserted or removed. However the code has pagination logic, so when changing a page every single item in the list is changed. This causes all the new items to fade in while all the old items are still fading out. So for around 300ms the list is double the size which causes the view to jump.
What I want to achieve is that the first 'page' of items finishes fading out before any new items start fading in, thus preventing the page from jumping.
The list
<div class="relative">
@for (item of items(); track item.id; let idx = $index) {
<list-item
@fadeInOut
[item]="item"
[idx]="idx"
>
</list-item>
}
</div>
Component:
Component({
/** ... **/
})
export class TaskListComponent {
/** ... **/
items = computed((): Item[] => {
const items = // signal from a store
const pagination = this.pagination(); // boolean
const paginationOffset = this.paginationOffset(); // increases with 10 on next page
let paginatedTasks = []
if (pagination) {
for(let i = 0; i < items.length; i++) {
if (i < paginationOffset + 10 && i >= paginationOffset) {
paginatedItems.push(items[i]);
}
}
} else {
paginatedItems = items;
}
return paginatedItems
});
}
Animation:
export const fadeInOutAnimation = trigger('fadeInOut', [
state('void', style({ opacity: 0,})), // Initial state when the element is not present
transition(':enter', [animate('300ms ease-in')]), // When the element enters
transition(':leave', [animate('300ms ease-out')]) // When the element leaves
]);
I am trying to animate the change of items in a list in angular. The animation should be a simpel fade-in-out. This works absolutely fine for individual items getting inserted or removed. However the code has pagination logic, so when changing a page every single item in the list is changed. This causes all the new items to fade in while all the old items are still fading out. So for around 300ms the list is double the size which causes the view to jump.
What I want to achieve is that the first 'page' of items finishes fading out before any new items start fading in, thus preventing the page from jumping.
The list
<div class="relative">
@for (item of items(); track item.id; let idx = $index) {
<list-item
@fadeInOut
[item]="item"
[idx]="idx"
>
</list-item>
}
</div>
Component:
Component({
/** ... **/
})
export class TaskListComponent {
/** ... **/
items = computed((): Item[] => {
const items = // signal from a store
const pagination = this.pagination(); // boolean
const paginationOffset = this.paginationOffset(); // increases with 10 on next page
let paginatedTasks = []
if (pagination) {
for(let i = 0; i < items.length; i++) {
if (i < paginationOffset + 10 && i >= paginationOffset) {
paginatedItems.push(items[i]);
}
}
} else {
paginatedItems = items;
}
return paginatedItems
});
}
Animation:
export const fadeInOutAnimation = trigger('fadeInOut', [
state('void', style({ opacity: 0,})), // Initial state when the element is not present
transition(':enter', [animate('300ms ease-in')]), // When the element enters
transition(':leave', [animate('300ms ease-out')]) // When the element leaves
]);
Share
Improve this question
asked Jan 20 at 15:23
crazythingcrazything
551 silver badge7 bronze badges
1 Answer
Reset to default 1I ended up setting a 150ms delay and setting display:none to make the item disappear completely before animating in the new list. This seems to work in all my required cases.
export const fadeInOutListItemAnimation = trigger('fadeInOutListItem', [
state('void', style({ opacity: 0, display: 'none'})), // Initial state when the element is not present
transition(':enter', [
animate('150ms 150ms ease-in', style({ opacity: 1, display: '*'}))
]), // When the element enters
transition(':leave', [
animate('150ms ease-out', style({ opacity: 0, display: 'none' })),
]) // When the element leaves
]);