Issue
Whenever you interact with one call of the carousel (i.e. clicking next or prev) the animation plays for both instances of the component. What is wrong here?
carousel.component.ts
@Component({
selector: 'app-carousel',
standalone: true,
templateUrl: './carousel.component.html',
imports:[ CommonModule ],
styleUrls: ['./carousel.component.scss'],
animations: [ CarouselAnimation ]
})
export class CarouselComponent {
@Input() items: string[] = [];
@Input() itemsPerSlide: number = 0;
@Input() carouselName:string = "";
currentIndex: number = 0;
hasNextItems: boolean = true;
get groupedItems(): string[][] {
const result: string[][] = [];
for (let i = 0; i < this.items.length; i += this.itemsPerSlide) {
result.push(this.items.slice(i, i + this.itemsPerSlide));
}
return result;
}
next() {
const nextIndex = (this.currentIndex + 1) % this.groupedItems.length;
this.hasNextItems = this.groupedItems[nextIndex].length > 0;
if (this.hasNextItems) {
this.currentIndex = nextIndex;
}
}
prev() {
const prevIndex = (this.currentIndex - 1 + this.groupedItems.length) % this.groupedItems.length;
const prevItemsPerSlide = this.groupedItems[prevIndex].length;
if (prevItemsPerSlide > 0) {
this.hasNextItems = true;
this.currentIndex = (this.currentIndex - 1 + this.groupedItems.length) % this.groupedItems.length;
}
}
}
carousel.component.html
<div id="DynamicCarousel" class="carousel slide carousel-fade" data-ride="carousel">
<div class="carousel-inner">
<div *ngFor="let itemGroup of groupedItems; let i = index" [class.active]="i === currentIndex" class="carousel-item" [@fadeInOut]>
<div class="d-flex justify-content-around">
<div *ngFor="let item of itemGroup" class="carousel-inner-item">
<img class="d-block w-100" [src]="item" alt="Slide {{i + 1}}">
</div>
</div>
</div>
</div>
<a class="carousel-prev" href="#DynamicCarousel" role="button" data-slide="prev" (click)="prev()">
<div class="icon-container">
<i class="fa fa-solid fa-arrow-left"></i>
</div>
</a>
<a class="carousel-next" href="#DynamicCarousel" role="button" data-slide="next" (click)="next()">
<div class="icon-container">
<i class="fa fa-solid fa-arrow-right"></i>
</div>
</a>
</div>
animations.ts
export const CarouselAnimation = [
trigger('fadeInOut', [
transition(':enter', [
style({ opacity: 0 }),
animate('300ms ease-in', style({ opacity: 1 }))
]),
transition(':leave', [
animate('300ms ease-out', style({ opacity: 0 }))
])
])
]
Usage
<h2>Carousel</h2>
<app-carousel [items]="carouselItems" [itemsPerSlide]="3" [carouselName]="'Carousel'"></app-carousel>
<h2>Carousel2</h2>
<app-carousel [items]="carouselItems2" [itemsPerSlide]="3" [carouselName]="'Carousel2'"></app-carousel>
carousel item arrays:
carouselItems: string[] = [
'https://via.placeholder.com/800x400',
'https://via.placeholder.com/800x400',
'https://via.placeholder.com/800x400',
'https://via.placeholder.com/800x400',
];
carouselItems2: string[] = [
'https://via.placeholder.com/800x400',
'https://via.placeholder.com/800x400',
'https://via.placeholder.com/800x400',
'https://via.placeholder.com/800x400',
'https://via.placeholder.com/800x400',
'https://via.placeholder.com/800x400',
'https://via.placeholder.com/800x400',
'https://via.placeholder.com/800x400',
];
- Tried to change the trigger name to be independant.
- Tried making the id unique.
- Even tried duplicating the code (gross)
Solution
you have problems with change detection understanding.
On any interaction with your components there is new groupedItems
created which causes elements to be recreated and thus re:enter the dom = play animation.
To eliminate the bug you can add ChangeDetectionStrategy.OnPush
so change detection won't trigger in the carousel that was not touched
@Component({
...
changeDetection: ChangeDetectionStrategy.OnPush,
})
Answered By - Andrei
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.