Changing the active Vuetify Tabs as you scroll

I have a Vuetify tabs setup that utilizes vue-scrollto to scroll to a specific position when a tab is clicked.

       <v-tabs
          centered
          grow
          color="#009EE2"
        >
          <div class="slider-background" />
          <v-tabs-slider />

          <v-tooltip
            bottom
            v-for="(tab, key) in tabs"
            :key="key"
            color="#009EE2"
          >
            <template v-slot:activator="{on}">
              <v-tab
                v-on="on"
                v-scroll-to="{
                  el: tab.scrollTo,
                  container: scrollContainer,
                  duration: 300,
                  easing: 'linear',
                  offset: -120,
                  force: true,
                  cancelable:true
                }"
              >
                <v-icon v-text="tab.icon" />
              </v-tab>
            </template>
            <div class="v-tooltip-arrow" />
            <span>
              {{ $t(tab.tooltipText) }}
            </span>
          </v-tooltip>
        </v-tabs>

Now, I am aiming to change the active tab based on the scrolling position.

Despite my efforts searching for a solution, I haven't come across any helpful resources. Here is the documentation I've consulted so far.

Is there a way to achieve this without resorting to JQuery?

For reference, here is an example showcasing the desired result using JQuery: http://jsfiddle.net/cse_tushar/Dxtyu/141/

Answer №1

By utilizing the href attribute for tabs along with an intersection observer, you can achieve this functionality.

Check out this basic, yet functional, example here: https://codepen.io/Qumez/pen/VwYEapg

The approach involves linking each tag with an anchor and connecting it to a data property. At the bottom of the page, there is a span with an intersection observer using Vuetify's v-intersect wrapper:

<span v-intersect ="handleIntersect">Page will automatically scroll to tab-3 when this span is in view</span>

This intersect wrapper triggers a user-defined method (in this instance, handleIntersect) to update the tab accordingly:

        handleIntersect(entries, observer) {
            if(entries[0].isIntersecting) {
                this.tab = "tab-3"
            }
            else {
                this.tab = "tab-1"
            }
        }

In your scenario, any item that could potentially change a tab based on its position in the viewport might require invoking a specific function with an argument specifying which tab to select. This concept aligns closely with what is demonstrated in the provided Pen.

Please Note: Although I haven't personally worked with IntersectionObserver before and I'm unsure if isIntersecting is the most effective way to determine an element's visibility in the viewport, it is advisable to conduct your own research and testing prior to incorporating this into production code :)

Answer №2

I successfully achieved this without relying on external libraries like vue-scrollto.

Below is the code for implementing tabs:

<v-tabs vertical v-model="tab_selected" >
      <span v-for="(category, index) in categories" :key="index">
        <v-tab @click="$vuetify.goTo('#sec_'+index)" class="nav_tab">
          {{category.name}}
        </v-tab>
      </span>

    </v-tabs> 

In this setup, tab selection is bound to a v-model and scrolling to the desired div is achieved using $vuetify.goTo(). More information can be found here.

The scrollable content is contained within a free-flowing div:

<div v-for="(category, index) in categories" :key="index">
        <v-card :id="'sec_'+index" class="card-shadow mb-10">
          <span :id="'span_'+index" v-intersect="handleIntersect"></span>
          ...
        </v-card>
      </div>

In this scenario, tabs and scrollable content are placed in a column layout of 4:8 respectively.

This functionality consists of two parts. Firstly, clicking on a tab should scroll to the corresponding content. This is managed through $vuetify.goTo(). Secondly, while scrolling the content div, the relevant tab should be selected based on visibility. This is handled by the v-intersect directive. More details can be found here.

<span :id="'span_'+index" v-intersect="handleIntersect"></span>

The handleIntersect function triggers when the specified span is within view. It detects the index of the visible span and activates the corresponding tab via v-model.

handleIntersect(entries, observer){
  let intersecting_element = entries[0]
  if(intersecting_element.isIntersecting){
    let id = intersecting_element.target.id
    let index = Number(id.split("_")[1])
    this.tab_selected = index
  }
}

See how it appears in action here: https://gyazo.com/388550a03d66e086d7dc00b646264806

Cheers!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unexpected behavior is being encountered with the else statement, and there are compatibility issues with IE and Mozilla Browser in the overall script

Script is functioning as expected in Google Chrome, but is not responsive in IE and Mozilla browsers JavaScript code: <script src="jquery.min.js"></script> <script> function Run() { if(jQuery('#inputtext').val() == '0 ...

AngularJS seems to be failing to display the initial option in the input select field

When using Angularjs, binding an input select to the model results in a new empty option being created <option value="? undefined:undefined ?"></option> Here is an example of the code: <select name="category" ng-model="hotspot.category"&g ...

JavaScript 'this' pointing to incorrect object

Unfortunately, this doesn't seem to be pointing to the correct object in this scenario. I'm having trouble figuring out how to reference the right one. function myObject() { this.someMethod1 = function() { var elementBtn = document.getEl ...

CSS animation stalling

While my angular app is loading all the necessary content through ajax, I display a loader on top of the content on a darker layer. The SVG used in this process contains an animateTransform: <svg width="38" height="38" viewBox="0 0 38 38" xmlns="http: ...

I'm noticing multiple repeated entries appearing when I try to set the cookie - what could be causing

Currently, I am utilizing the library js-cookie instead of my previous use of jquery.cookie. I have encountered an issue related to duplicating cookie entries. There are occasions when I invoke the following method: Cookies.set('my-cookie-name', ...

Troubleshooting Vue 3: Dealing with Synchronization Issues Between Keyboard Input and

I am currently working on a Vue 3 autocomplete component and I've come across a strange issue that I can't quite figure out. The component emits two events: "update:search" to update the search variable in the parent component, and "change" whic ...

What is the best way to check the difference between the current date and time with another date and

Seeking assistance in comparing 2 dates using JavaScript has been a bit challenging for me. I haven't found the exact solution on this platform yet. As a beginner in JavaScript, I initially assumed that obtaining the current date and time would be a s ...

AngularJS's ng-click function seems to be malfunctioning

Currently, I am in the process of learning angularJS with the help of the book titled "Learning Web Development with Bootstrap and AngularJs." One challenge I am facing is creating a ng-click functionality for a button in my project. Unfortunately, when I ...

Is it possible that when a user is redirected to a different URL, Chrome terminates any pending Ajax requests?

Currently, I have a function that allows the user to unlock a list they are currently editing: function cancelLock(id) { $.ajax({ type: "POST", url: "/ajax.php?action=cancelLock", dataType: 'json', data: "id="+ id }); retur ...

What is the process for incorporating an external script into my Vue methods?

After a user registers, I need to send them a confirmation email using vue.js. I am looking to implement the script provided by . How can I incorporate the "Email.send" method into my vue.js application? <script src="https://smtpjs.com/v3/smtp.js"> ...

fileuploader with clipboard functionality and easy drag-and-drop feature using HTML and JavaScript

I am in need of a file uploader that can be implemented using HTML and JS. My goal is to have it work on multiple platforms, specifically Google Chrome, FireFox, and IE9+, with the capability of copying and pasting screenshots as well as dragging and dropp ...

Discover the specific item within an array of objects

Anyone have information like this: const info = { Title : "Banana", Quantity : 10, Location : "Everywhere", Phone : 123456, A : 987, B : 654, } and there is another array of details as: const dataArr = ["Title",&q ...

Bigcommerce encounters a 401 error during the payment processing, triggered by API with error code 10001

I recently started working on integrating the Bigcommerce payment API and I am facing issues with solving the 401 unauthorized error. Below is a sample of the data that I have tried: { "payment": { "instrument": {}, "payment_method_id": "cod", "amoun ...

Issue with Bootstrap 4.x tooltip positioning within an overflowing container

In the world of bootstap 4.x, a tooltip finds itself in a bit of a pickle when nestled within a parent element sporting an overflow property. Whether it's overflow: auto; or overflow: scroll;, the poor tooltip just can't seem to find its place. T ...

Creating a custom video to use as the favicon for my website

Imagine this: With the help of this plugin, you can have a video playing as your site's favicon using the following code snippet: var favicon=new Favico(); var video=document.getElementById('videoId'); favicon.video(video); //stop favicon.v ...

The front end button stubbornly refuses to comply and redirect to another page

I am having trouble getting my button element to redirect my page to another page. I have tried using an onclick function inside the button tag with window.location.href, as well as creating a separate function for the redirect, but nothing seems to be wor ...

Utilize getJSON to refresh the JavaScript datetimepicker

I am currently using an api with ajax (getJSON) to append data to a specific div called 'open' on my website. However, I now want to update the static values in my datetime picker script for minTime and maxTime. Here is the code snippet: AJAX ...

Storing information in local storage as JSON using AngularJS

I am working on a form with the following fields: <form ng-submit="addState()"> <input ng-model="text1" type="text"> <input ng-model="text2" type="text"> <input ng-model="text3" type="text"> ...

Nuxt's production mode delays resource loading

I have encountered an issue with my Nuxt app where the CSS loads fine in development mode, but when switching to production mode, some of the styles are deferred. It seems like this may be related to the Vuetify CSS, as only some classes exist initially. ...

What is the best way to adjust a CSS width using the output from a JavaScript function?

I am facing a challenge with a GridView within a div wrapper. The row headers along the left side need to always be visible. So far, this setup is working fine. However, I need the wrapper to have a variable width to adjust to the browser size. Although I ...