Navigate to the top of the Vue scrollable list using v-auto-complete

I need to implement a feature that automatically scrolls to the top of a scrollable list every time the search input is changed. Currently, I have a list where multiple items can be selected, and I want it to reset to the top whenever a new search query is entered.

For example, if I type 'b' in the search bar and then scroll down, typing 'e' should bring me back to the very top of the list.

Below is an example code snippet demonstrating what I am trying to achieve. I have attempted two different methods using the scrollTop property of the HTML element and the goTo function from Vuetify, but neither approach has been successful so far.

Code demo -

In case the demo link expires, here is the actual code:

<div id="app">
    <v-app>
        <v-main class="py-3 px-5">
            <h1 class="teal--text">AutoComplete Infinite Scroll Example</h1>
            <v-autocomplete 
                id="autoComplete"
                ref="autoComplete"
                v-model="selected"
                :items="beers" 
                item-text="name" 
                item-value="id" 
                :search-input.sync="search"
                label="Search the beers.."
                return-object
                multiple
                autocomplete="off"
                >
                <template v-slot:append-item>
                  <div v-intersect="onIntersect" class="pa-4 teal--text">
                     Loading more items ...
                  </div>
                </template>
            </v-autocomplete>
      </v-main>
    </v-app>

new Vue({
    el: '#app',
    vuetify: new Vuetify(),
    data() {
        return {
          search:'',
          beers: [],
          selected: null,
          perPage: 30,
          page: 1,
        }
    },
    methods: {
        getBeers() {
            console.log('page', this.page)
            const apiUrl = `https://api.punkapi.com/v2/beers?page=${this.page}&per_page=${this.perPage}`
            axios.get(apiUrl)
                .then(response => {
                  this.beers = [
                      ...this.beers,
                      ...response.data
                  ]
            })
        },
        onIntersect () {
            console.log('load more...')
            this.page += 1
            this.getBeers()
        },
    },
    watch:{
        search:function(){
         //first method
          let myId=document.getElementById('autoComplete')
          if(myId){
            myId.scrollTop = 0
    
          }
          
          //second method with ref  and vuetify goto
          this.$nextTick(() => {
            this.$vuetify.goTo(this.$refs.autoComplete) 
          })
        }
    },
    created() {
        this.getBeers()
    }
})

Answer №1

If you're looking for a solution similar to this (check out the demo on the full page)

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
 data: () => ({
    beers: [],
          selected: null,
          perPage: 30,
          page: 1,
  
  }),
     created() {
        this.getBeers()
    },
  methods: {
    goToTop(){
      this.beers = [];
      this.page = 1;
      this.getBeers();
    },
       getBeers() {
            console.log('page', this.page)
            const apiUrl = `https://api.punkapi.com/v2/beers?page=${this.page}&per_page=${this.perPage}`
            axios.get(apiUrl)
                .then(response => {
                  this.beers = [
                      ...this.beers,
                      ...response.data
                  ]
            })
        },
            onIntersect () {
            this.page += 1
            this.getBeers()
        },
  },
})
.scroll-to-top {
  position:sticky;
  bottom:8px;
  width:100%;
  display:flex;
  justify-content :right;
  background-color: rgba(0, 0, 0, 0); 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.24.0/axios.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0b6d64657f4b3f2573">[email protected]</a>/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7d0b0809051817043d4f53">[email protected]</a>/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1c6a69695c2e3254">[email protected]</a>/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8ff9fafafbf6f9f6cffdd1}">[email protected]</a>/dist/vuetify.js"></script>


 <div id="app">
  <v-app id="inspire">
    <v-card>
      <v-container fluid>
        <v-row
          align="center"
        >
          <v-col cols="12">
            <v-autocomplete 
                v-model="selected"
                :items="beers" 
                item-text="name" 
                item-value="id" 
                label="Search da beers.."
                return-object
                autocomplete="off"
                >
              
          
               <template v-slot:append-item>
                 <div v-intersect="onIntersect" class="pa-4 teal--text">
                     Loading more items ...
                  </div>
                            <div class="text-right pr-4 scroll-to-top">
                              <v-btn
                                color="primary"
                                small
                                class="align-right"
                                @click="goToTop"
                              >
                                 Go to top
                              </v-btn>
                            </div>
                          </template>
            </v-autocomplete>
          </v-col>
        </v-row>
      </v-container>
    </v-card>
  </v-app>
</div>

Answer №2

My approach to this problem was inspired by zergski's solution.

I had to do some casting due to typescript.

scrollToTop(): void {
  let scrollContainer = document.querySelector('.v-autocomplete__content')

  let firstItem = document.querySelector('.company-item-name') as HTMLElement

  if (scrollContainer && firstItem && firstItem.offsetTop) {
    scrollContainer.scrollTop = firstItem.offsetTop
  }
},

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

Dealing with special characters in Mustache.js: handling the forward slash

I have a JSON file that contains information about a product. Here is an example of the data: { "products": [ { "title": "United Colors of Benetton Men's Shirt", "description": "Cool, breezy and charming – this s ...

Does anyone know of a convenient tool that can automatically provide suggested street names for mailing addresses in every country across the globe, for free?

Is there a convenient tool that automatically completes street addresses for various countries worldwide? I'm considering options similar to YQL from Yahoo or Foursquare. I'd like to provide users with suggestions of known street names as they ...

Tips for generating JSON data in the correct format dynamically while continuously adding new information to the existing object

In my form, users input their email and password, which then generates dynamic JSON upon submission. However, I encountered an issue where the JSON gets corrupted when logging in with different user details as it updates the existing JSON with a new object ...

Execute jQuery after Angular has completed its loading process

I'm currently working on making some small adjustments to an existing website. This website was originally created using Angular. While my code is written with jQuery, I do have the flexibility to use any type of JavaScript necessary. Despite this, ...

Next.js Server Error: ReferenceError - 'window' is undefined in the application

I am currently in the process of integrating CleverTap into my Next.js application. I have followed the guidelines provided in the documentation Web SDK Quick Start Guide, however, I encountered the following issue: Server Error ReferenceError: window is ...

Vue.js tutorial: Disabling button dynamically based on empty data array

My project involves creating a shopping cart application using Vue.js: var app = new Vue({ el: "#app", data: { items: [ { id: 1, name: "Item 00", spec: "spec 00", price: 400, quantity: 1, unit: &quo ...

What is the reason behind the necessity for a React class component to always invoke super(props) within its constructor function?

I recently came across a tutorial from reactjs.org that mentioned the importance of calling the base constructor with props in class components. However, further research led me to a StackOverflow answer suggesting that super() can be used instead of super ...

My current objective is to extract the information from a specific item within a combobox by implementing the following code

alert($("select[name="+this.name+"] option:selected").text()); However, I am not receiving any output unless I explicitly specify the name of the combobox instead of using this.name. This issue may be related to the way quotes are being handled. ...

How can the @blur event be added to the vue-bootstrap-typeahead in Nuxt/Vue application?

I am facing an issue where I want to trigger a function upon leaving an input field. The input in question is set up using vue-bootstrap-typeahead. Upon inspecting the DOM, I found that the structure of the input element looks like this: <div id="m ...

Having trouble generating an image with JavaScript

I am currently working on incorporating an image onto a webpage using JavaScript. Surprisingly, even the alert('This function works!') is not displaying anything! What could be causing this issue? Please assist! <!DOCTYPE html> <html> ...

Troubleshooting issues with Ajax and Jena

Whenever I attempt to utilize AJAX to call Jena in my servlet, I encounter this error: java.lang.ClassNotFoundException: com.hp.hpl.jena.sparql.core.Prologue at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1516) at org.apa ...

Optimizing Backend Access with Laravel and Vue JS: How to Choose the Most Effective Approach

Currently, I am utilizing Laravel API passport to handle authentication in my Single Page Application (SPA) built with Vue. At the moment, whenever I need to access the backend server, I have to include a header in order to be allowed through the protected ...

Is it possible to pass a parameter to an NGXS action that is not the Payload?

I am working on implementing an Ngxs action that includes a parameter in addition to the payload. This parameter is used to determine whether or not a notification should be sent. @Action(UpdateUser) async UpdateUser( ctx: StateContext<ProfileStat ...

Built-in Promises within MongoDB

Is there a way to determine which methods in mongoDb have an inbuilt promise? For example, "updateOne() , findOne()" have inbuilt promises that we can access using ".then", but many other mongoDB methods lack this feature. How can we identify which methods ...

Combine all of Nuxt.js into one output file

Currently, I am working with a basic Nuxt.js application and I am curious to know if it is feasible to compile the output into a single file, combining all the .js and .css files altogether? I came across a solution for achieving this using just Vue.js as ...

What is the best way to dismiss the modal window in React upon clicking the "Add product" button?

Hello all, I'm having trouble figuring out how to close the modal window in React. I want it so that when the user clicks on the "Add" button, a modal window opens for data input, and then upon clicking the "Add product" button, the window closes imme ...

Tips for managing the onblur event using selenium automation framework

I want to trigger an onblur event when I click away using JavaScript. I tried the following code: ((JavascriptExecutor)getDriverProvider().executeScript("document.getElementByXpath('xpath here').onblur();"); However, it doesn't seem to wo ...

Extract the text enclosed by two specific symbols within a string and add it to a new array

I have a string formatted as follows: var str = "-#A This text belongs to A. Dummy Text of A. -#B This text belongs to B. Dummy Text of B. -#C This text belongs to C. Dummy text of C. -#Garbage This string should be ignored" I am looking to convert this ...

What is the best way to ensure that the content container's max-width for a split tier is the same as the width of a full-width tier?

My goal is to create a split tier on a webpage with a 60/40 layout. The size of this tier should be calculated based on the maximum width of the container above it. Using JavaScript and jQuery, I managed to derive the max-width value of the full-width-tier ...

Is it important to minify JavaScript npm packages?

In my journey of creating numerous npm packages, I find myself pondering over the question: "Should JavaScript npm packages be minified?" I have always held the belief that minifying already minified code is not a good practice, which is why I have refrai ...