cssvue.jsvue-componentbootstrap-vuescrollspy

Bootstrap Vue scrollspy not working on dynamic data. On inspection, all elements are active(highlighted) one by one when passed


I have a Vue application that shows content on the basis of the component type(Header, Text, Image) in my JSON file. I need to scroll spy on the Header component that has my headings.

I am using Bootstrap Vue Scrollspy ( https://bootstrap-vue.js.org/docs/directives/scrollspy/) and I have issues with the scrollspying, as in the highlighting of the menu item when the referenced item is reached. On inspecting my CSS, every time I scroll down to the second header, my second header in my sidebar becomes active(this is fine) but my first header still remains to stay active. Usually, the first header should turn back to normal. But in my case, all my headers are active in my sidebar when I reach the bottom of the page. Maybe it's because of dynamic data and because Vue sees them all as different components and it doesn't really know that the referenced item has passed already? I tried wrapping up my Header Component in a <div>, <section> but nothing seems to work. Would appreciate some help. Thanks!

This is what I have:

<template>
 <div>
  <div v-sticky class="sidebar_content">
        <h5>Side Bar</h5>
        <div
          v-for="(item, index) in article.mainContent['en']"
          id="side_bar_list"
          :key="index"
        >
          <div v-if="item.component === 'heading'">    <--- Scrollspy menu on my sidebar
            <b-list-group v-b-scrollspy>
              <b-list-group-item
                :href="`#header-${index}`"
                >{{ item.settings.text }}</b-list-group-item
              >
            </b-list-group>
          </div>
  </div>
  <div v-for="(item, index) in article.mainContent['en']" :key="index">

          <image-component v-if="item.component === 'image'">{{
            item.settings.image.path
          }}</image-component>

          <header-component                           <--- This is what I am scrollspying on
            v-if="item.component === 'heading'"
            :id="`header-${index}`"
            >{{ item.settings.text }}</header-component>


          <text-component
            v-if="item.component === 'text'"
            >{{ item.settings.text }}</text-component>

  </div>
 </div>
</template>

Solution

  • You need to move your v-b-scollspy directive to your sidebar wrapper element:

    <div v-sticky class="sidebar_content" v-b-scrollspy>
      <h5>Side Bar</h5>
      <b-list-group id="side_bar_list">
        <template v-for="(item, index) in article.mainContent['en']">
          <b-list-group-item
            v-if="item.component === 'heading'"
            :key="index"
            :href="`#header-${index}`"
          >{{
            item.settings.text
          }}</b-list-group-item>
        </template>
      </b-list-group>
    </div> <!-- end of side bar -->
    
    <!-- main content divs -->
    <div v-for="(item, index) in article.mainContent['en']" :key="index">
      <image-component v-if="item.component === 'image'">{{
        item.settings.image.path
      }}</image-component>
      <header-component
        v-if="item.component === 'heading'"
        :id="`header-${index}`"
      >{{
        item.settings.text
      }}</header-component>
      <text-component v-if="item.component === 'text'">{{
        item.settings.text
      }}</text-component>
    </div>