angularbootstrap-5scrollspy

Creating a scrollspy manually in Angular


I have set up scrollspy inside a MatDialog, and the event activate.bs.scrollspy doesn't seem to fire, or maybe it does fire, but probably at a window level, and it doesn't highlight the anchors on my navbar, as I scroll down. I'm using Angular 17 and bootstrap 5.3.

<div id="scrollContainer" class="row">
    <nav id="scrollspy-navbar" class="col-4 navbar-light flex-column align-items-stretch pe-4 border-end overflow-auto">
        <nav class="nav nav-pills flex-column">
            <a class="nav-link" href="#item-01">{{heading01}}</a>
            <a class="nav-link" href="#item-02">{{heading02}}</a>
            <a class="nav-link" href="#item-03">{{heading03}}</a>
            <a class="nav-link" href="#item-04">{{heading04}}</a>
            <a class="nav-link" href="#item-05">{{heading05}}</a>
        </nav>
    </nav>

    <div id="scrollspy-panel" 
         class="col-8 px-3" 
         data-bs-spy="scroll" 
         data-bs-target="#scrollspy-navbar" 
         data-bs-smooth-scroll="true" 
         tabindex="0">
        <div id="item-01">
            <p>...</p>
        <div id="item-02">
            <p>...</p>
        <div id="item-03">
            <p>...</p>
        <div id="item-04">
            <p>...</p>
        <div id="item-05">
            <p>...</p>

My css

#scrollspy-navbar {
    height: 60vh;
    overflow-y: scroll;
}

#scrollspy-panel {
    height: 60vh;
    overflow-y: scroll;
}

I have tried to listen to activate.bs.scrollspy without using jquery, as it's considered bad practice in the latest versions of Angular. I tried using @HostListener but I don't think I can catch activate.bs.scrollspy with that.

I've also tried

    <div id="scrollspy-panel" 
         class="col-8 px-3" 
         data-bs-spy="scroll" 
         data-bs-target="#scrollspy-navbar" 
         data-bs-smooth-scroll="true" 
         tabindex="0" 
         (scroll)="onPanelScroll($event)">

and then

  onPanelScroll (e:any):void {
    console.log(e.currentTarget);
  }

but it logs the entire <div id="scrollspy-panel"> itself, and not the particular <div id="item-0X"> item on display.

I read that in bootstrap 5.3 I'm supposed to capture e.relatedTarget on activate.bs.scrollspy but I've no idea how to do that without using jquery.

Is there a way I can

If anyone could help me in any of these ways or with any other useful suggestions, or respond in a friendly way without causing offence, that would be greatly appreciated.


Solution

  • In the component, instantiate scroll spy with JavaScript instead, as it seems that data attributes don't work well with dynamically added content.

    Try this (remove data attributes from template HTML):

      ngAfterViewInit() {
        const scrollSpy = new bootstrap.ScrollSpy('#scrollspy-panel', {
          target: '#scrollspy-navbar'
        });
      }