Search code examples
javascriptvue.jsnuxt.jsbootstrap-vuescrollspy

How can I get the active element/currently viewed section's heading and display it (Bootstrap Vue ScrollSpy)?


I am referring to the Bootstrap Vue Scrollspy(https://bootstrap-vue.org/docs/directives/scrollspy/#scrollspy). I am using Nuxt js.

My elements are referenced correctly and are spying on the content. I would like to get the element/section that is currently being viewed to be updated in a div. I know that an active class is added to the element/section being viewed, but I am not sure how to get it.

This is what I have:

 <div id="mobilescrollspy">          <--- Scrollspy headings in a dropdown     
        <b-nav v-b-scrollspy>
          <b-nav-item-dropdown text="Dropdown">
            <b-dropdown-item class="text-base self-center" href="#item-1">
              Item 1 Heading
            </b-dropdown-item>
            <b-dropdown-item class="text-base self-center" href="#item-2">
              Item 2 Heading
            </b-dropdown-item>
            <b-dropdown-item class="text-base self-center" href="#item-3">
              Item 3 Heading
            </b-dropdown-item>
          </b-nav-item-dropdown>
        </b-nav>
</div>

<div class="content">                <--- The content itself
  <div id="item-1">
      This is the content for item 1
  </div>
  <div id="item-2">
      This is the content for item 2
  </div>
  <div id="item-3">
      This is the content for item 3
  </div>
</div>

If item 2 is in view, I want a text that shows: "Item 2 Heading", once I scroll to item 3, this div gets updated to "Item 2 Heading". How can I achieve this? Thanks for the help!


Solution

  • The event listener documented in scrollspy's documentation gives you the id of the currently active element. You can use it to display whatever you want.

    I've put up a basic example here: https://codesandbox.io/s/competent-cherry-o4o6h?file=/src/App.vue

    It's basic because it queries $el to find the active element and get it's innerHTML. Instead, in a real app, you could directly reference the object in the navigation which you used to render the navigation in the first place (and therefore avoid querying DOM).

    To create this example, I only used code from the documentation, I added a computed property (getSectionTitle), and one optional feature: I noticed when scrolling to top there is no event emitted and I thought it would be good if I cleared the selected section (just as scrollspy no longer selects any element). So I added a scrollListener, in mounted, removed in beforeDestroy, which, when #nav-scorller scrolls to top, resets section to ''.
    Other than that, it's quite basic.

    Again, this extra listener is not really necessary. I just thought it would be good to show how it could be done, to serve as an example for anyone who might need it in the future.