How to achieve this :
When I click on right arrow of the carousel, I want to trigger a method with the item index as parameter.
Some thing like <button ... (...)="eventHandler(index)" ..>
Below the code to be modified to achieve passing index param (the code is working)
<div id="carouselId" class="carousel slide">
<div class="carousel-inner" >
<div class="carousel-item active">
<img [src]="videoFirstItem.safeUrl">
</div>
<div class="carousel-item" *ngFor="let item of videoItems">
<img [src]="item.safeUrl">
</div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#carouselId" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#carouselId" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
const PAGE_INDEX:number=0
const NB_ITEMS_PER_PAGE:number=4
@Component({
selector: 'app-image-carousel',
templateUrl: './image-carousel.component.html',
styleUrls: ['./image-carousel.component.css']
})
export class ImageCarouselComponent implements OnInit {
videoFirstItem:DisplayableVideo=new DisplayableVideo
videoItems:DisplayableVideo[]=new Array<DisplayableVideo>
constructor(
private backendVideRetrieverService: BackendVideRetrieverService
){}
ngOnInit(): void {
this.backendVideRetrieverService.getVideosByPage(PAGE_INDEX, NB_ITEMS_PER_PAGE).subscribe(
(displayableVideos:DisplayableVideo[]) => {
this.videoFirstItem = displayableVideos[0]
this.videoItems=displayableVideos.slice(1)
}
)
}
}
Below the code that is not working but gives an idea of what I want to do
<div class="carousel-item" *ngFor="let item of videoItems; let index = index">
....
<button class="carousel-control-next" ... data-bs-slide="next" (clilk)="eventHandler(index)">
eventHandler(index:number){
if(index == lastItemIndex){
getMoreVideo()
}
}
The problem is you cannot access index outside ngFor context.
One way to access index is via Bootstrap's Carousel instance which tracks active element: so, assign index to each carousel item, and then add click handler on prev/next, and get carousel instance and active element, and then read the index you stored:
store index on carousel item:
<div class="carousel-item" *ngFor="let item of videoItems let index = index" [attr.data-index]="index">
add click handler (no arguments needed, because it's outside of scope, it's just to check index from carousel's active element):
<button class="carousel-control-next" type="button" data-bs-target="#carouselId" data-bs-slide="next" (click)="eventHandler($event)">
on prev/next click, get carousel instance with Bootstrap, and then implement handler to read carousel's active element, and then get its index value you stored in data attribute:
// import Bootstrap's carousel
import { Carousel } from 'bootstrap';
// instance
carousel!: Carousel & { _activeElement?: null | HTMLElement };
ngAfterViewInit(): void {
// instantiate when rendering is done
this.carousel = new Carousel('#carouselId');
// or with .getOrCreateInstance method
//this.carousel = Carousel.getOrCreateInstance('#carouselId'))
}
eventHandler(event:Event){
// get active element and read its index
const index = this.carousel._activeElement.dataset.index;
console.log('index', index);
// do something with index...
if(index == lastItemIndex){
getMoreVideo()
}
}
(if you're interested only in detecting last item, you could use Angular's last
and add some flag only to the last element, for example:
<div class="carousel-item" *ngFor="let item of videoItems; let last = last;" [attr.data-islast]="last ? 'true': null">
edit:
You can also access active element via carousel's slide
event's relatedTarget
:
add slide.bs.carousel
listener to carousel container (note that it will be called whenever the carousel slides, for example, if autoplaying):
<div id="carouselId" class="carousel slide" (slide.bs.carousel)="onSlide($event)">
slide handler recieves bootstrap's event
and then its relatedTarget
is the item to be active:
onSlide(event: any) { // Carousel.Event
// event.relatedTarget is the DOM element that is being slid into place as the active item
const activeItem = event.relatedTarget; // as HTMLElement;
const index = activeItem.dataset.index;
console.log('index', index);
//...
}
see:
Events
Bootstrap’s carousel class exposes two events for hooking into carousel functionality. Both events have the following additional properties:
direction
: The direction in which the carousel is sliding (either"left"
or"right"
).relatedTarget
: The DOM element that is being slid into place as the active item.from
: The index of the current itemto
: The index of the next item