Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
152 views
in Technique[技术] by (71.8m points)

html - How to properly use an autocomplete input field based on a database source in Vue?

I want to use an input field (or something similar) that suggests an autocomplete, based on records from a data source.

In Vue I retrieve an array from a database table containing 3000+ records:

data(){
    return{
      inboundRelation_Trelation_data: [],
    }
  },

mounted(){

     axios.get('/app/wms/allRelations', {
                  params: {
                    "dbConn": this.connString,
                  }
                })
     .then(response => this.inboundRelation_Trelation_data = response.data);
  },

Based on this data, I want an autocomplete input field and/or dropdown. I've found 2 approaches online.. 1:

<select v-model="form.CUSTOMER_NAME">
                <option v-for="(relation, index) in inboundRelation_Trelation_data" :value="relation.RELATIONCODE" v-text="relation.COMPANYNAME + ' | ' + relation.RELATIONCODE"></option>
</select>

This populates a dropdown, but my users experience this as tedious, as they need to type their letters quickly, otherwise after a small pause (like <0.5s), the next typed letter will start a new search and the results are inconsistent.

The other approach is using a data-list:

<input list="allRelations" type="text" @focus="$event.target.select()" v-model="form.CUSTOMER_NAME">
              <datalist id="allRelations">
                <option v-for="(relation, index) in inboundRelation_Trelation_data" :value="relation.RELATIONCODE" v-text="relation.COMPANYNAME + ' | ' + relation.RELATIONCODE"></option>
</datalist>

This works perfectly for small amounts of data. But when dealing with 100+ records (or 3000+ in this case), the whole browser freezes upon typing a letter. For some reason this is a very resource-heavy implementation. I've found some people with similar issues, but no solutions.

At the end of the day, I just want my users to be able to search in a huge list of 3000+ records. How do I approach this?

question from:https://stackoverflow.com/questions/66062006/how-to-properly-use-an-autocomplete-input-field-based-on-a-database-source-in-vu

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use vue-autosuggest package by this github link :
https://github.com/darrenjennings/vue-autosuggest

I am using this package and my data loads as my expect.

This is the template that you can use:

<template>
<div class="autosuggest-container">
  <vue-autosuggest
    v-model="form.CUSTOMER_NAME"
    :suggestions="filteredOptions"
    @focus="focusMe"
    @click="clickHandler"
    @input="onInputChange"
    @selected="onSelected"
    :get-suggestion-value="getSuggestionValue"
    :input-props="{
      class: 'form-control',
      id: 'autosuggest__input',
      field: 'CUSTOMER_NAME',
      placeholder: 'Enter customer name for auto suggest',
    }"
  >
    <div
      slot-scope="{ suggestion }"
      style="display: flex; align-items: center"
    >
      <img
        :style="{
          display: 'flex',
          width: '25px',
          height: '25px',
          borderRadius: '15px',
          marginLeft: '10px',
        }"
        :src="suggestion.item.avatar"
      />
      <div style="{ display: 'flex', color: 'navyblue'}">
        {{ suggestion.item.CUSTOMER_NAME }}
      </div>
    </div>
  </vue-autosuggest>
</div>

And the Script section:

<script>
export default {
  data() {
    return {
      searching: false,
      query: '',
      selected: '',
      suggestions: [],
    }
  },
  computed: {
    filteredOptions() {
      return [
        {
          data: this.suggestions.filter((option) => {
            return (
              option.name.toLowerCase().indexOf(this.query.toLowerCase()) > -1
            )
          }),
        },
      ]
    },
  },
  methods: {
    clickHandler() {
      //
    },
    onSelected(item) {
      this.selected = item.item
    },
    async onInputChange(text = '') {
      this.searching = true
      await this.$axios
        .get(`/app/wms/allRelations`,{
                  params: {
                    "dbConn": this.connString,
                  })
        .then((res) => {
          this.suggestions = res.data.data
        })
        .catch((e) => console.log(e))
        .finally(() => (this.searching = false))
    },
    getSuggestionValue(suggestion) {
      return suggestion.item.name
    },
    focusMe(e) {
      this.onInputChange()
    },
  },
}
</script>

If still your browser freeze, you have to change your API response limit to something like descended 10 items.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...