question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Select component with search (like Select2)

See original GitHub issue

Is your feature request related to a problem? Please describe…

If the option list for <select> elements (i.e. <b-form-select :options="options" />) becomes long, users cannot easily find what they want to select. This is especially true if the option list is sorted by value, and not by label text (e.g. with localized labels, but that’s easy to overcome).

This is a shortcoming of the Browser’s UI capabilities, providing no search for <select> elements. Once opened, the user can start typing, and the option list is matched (but only with a prefix match). This only works reliably on desktop browsers.

There’s also a <datalist> element, which allows searching/matching, but last time I checked, it didn’t behave like a dropdown list and allowed entering custom values.

Describe the solution you’d like

I’d like to have either an option to <b-form-select>, or a separate component which implements something like Select2, Chosen or Vue Select:

An input field for the user to search options + a dropdown list with matching options.

If no match is found, a short message indicating this fact should displayed instead of the dropdown list. Allowing new values should not be possible (or at least be disabled by default).

Describe alternatives you’ve considered

  • Typeahead, Select2, Chosen require jQuery
  • Vue Select requires extra work to make it look like the rest of the application (no Bootstrap styling)
  • Vue Selectize mostly does what I want, but brings redundant features (sth. similar to <b-form-tags>), thus increasing the bundle size; it also has no Bootstrap styling
  • <datalist> allows entering new values, and needs custom styling (adding a class="form-control" might do the trick)
  • <b-form-input> combined with <b-dropdown> this is my current approach. It requires a bit CSS hackery to properly position the dropdown list and a larger chunk of JS code to open/close/filter the list.

Additional context

Vue Selectize, Example “Single Item Select”
image

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:4
  • Comments:5

github_iconTop GitHub Comments

3reactions
arunavo4commented, Nov 22, 2020

Adding some Starter Code for anyone willing to hack away. This works but the only difference is it uses HTML input and not b-form-input.

<template>
  <div class="dropdown" v-if="options">

    <!-- Dropdown Input -->
    <input class="dropdown-input"
      :name="name"
      @focus="showOptions()"
      @blur="exit()"
      @keyup="keyMonitor"
      v-model="searchFilter"
      :disabled="disabled"
      :placeholder="placeholder" />

    <!-- Dropdown Menu -->
    <div class="dropdown-content"
      v-show="optionsShown">
      <div
        class="dropdown-item"
        @mousedown="selectOption(option)"
        v-for="(option, index) in filteredOptions"
        :key="index">
          {{ option.name || option.id || '-' }}
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    name: 'Dropdown',
    template: 'Dropdown',
    props: {
      name: {
        type: String,
        required: false,
        default: 'dropdown',
        note: 'Input name'
      },
      options: {
        type: Array,
        required: true,
        default: () => [],
        note: 'Options of dropdown. An array of options with id and name',
      },
      placeholder: {
        type: String,
        required: false,
        default: 'Please select an option',
        note: 'Placeholder of dropdown'
      },
      disabled: {
        type: Boolean,
        required: false,
        default: false,
        note: 'Disable the dropdown'
      },
      maxItem: {
        type: Number,
        required: false,
        default: 6,
        note: 'Max items showing'
      }
    },
    data() {
      return {
        selected: {},
        optionsShown: false,
        searchFilter: ''
      }
    },
    created() {
      this.$emit('selected', this.selected);
    },
    computed: {
      filteredOptions() {
        const filtered = [];
        const regOption = new RegExp(this.searchFilter, 'ig');
        for (const option of this.options) {
          if (this.searchFilter.length < 1 || option.name.match(regOption)){
            if (filtered.length < this.maxItem) filtered.push(option);
          }
        }
        return filtered;
      }
    },
    methods: {
      selectOption(option) {
        this.selected = option;
        this.optionsShown = false;
        this.searchFilter = this.selected.name;
        this.$emit('selected', this.selected);
      },
      showOptions(){
        if (!this.disabled) {
          this.searchFilter = '';
          this.optionsShown = true;
        }
      },
      exit() {
        if (!this.selected.id) {
          this.selected = {};
          this.searchFilter = '';
        } else {
          this.searchFilter = this.selected.name;
        }
        this.$emit('selected', this.selected);
        this.optionsShown = false;
      },
      // Selecting when pressing Enter
      keyMonitor: function(event) {
        if (event.key === "Enter" && this.filteredOptions[0])
          this.selectOption(this.filteredOptions[0]);
      }
    },
    watch: {
      searchFilter() {
        if (this.filteredOptions.length === 0) {
          this.selected = {};
        } else {
          this.selected = this.filteredOptions[0];
        }
        this.$emit('filter', this.searchFilter);
      }
    }
  };
</script>


<style lang="scss" scoped>
  .dropdown {
    position: relative;
    display: block;
    margin: auto;
    .dropdown-input {
      background: #fff;
      cursor: pointer;
      border: 1px solid #e7ecf5;
      border-radius: 3px;
      color: #333;
      display: block;
      font-size: .8em;
      padding: 6px;
      min-width: 250px;
      max-width: 250px;
      &:hover {
        background: #f8f8fa;
      }
    }
    .dropdown-content {
      position: absolute;
      background-color: #fff;
      min-width: 248px;
      max-width: 248px;
      max-height: 248px;
      border: 1px solid #e7ecf5;
      box-shadow: 0px -8px 34px 0px rgba(0,0,0,0.05);
      overflow: auto;
      z-index: 1;
      .dropdown-item {
        color: black;
        font-size: .7em;
        line-height: 1em;
        padding: 8px;
        text-decoration: none;
        display: block;
        cursor: pointer;
        &:hover {
          background-color: #e7ecf5;
        }
      }
    }
    .dropdown:hover .dropdowncontent {
      display: block;
    }
  }
</style>
3reactions
dmkecommented, Nov 9, 2020

Addendum

I’ve found these issues (after creating this one, of course 🙄) which mention a search/filter functionality.

  • #5367 promising this feature in a “near-future release” (May 2020)
  • #5235 “in a month-ish” (April 2020)
  • #3162 (probably outdated)

It looks like, this feature is on the way. Is there a way to beta-test it?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Search | Select2 - The jQuery replacement for select boxes
Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and pagination (infinite scrolling) of results.
Read more >
Select Box with Search Option | Jquery Select2 - YouTube
Select Box with Search Option | Jquery Select2 | HTML Select optionSelect2 js library is designed to add search to the normal select...
Read more >
Creating a select box with a search option - Stack Overflow
Incase you need to use only select tag use Selectize Js. It has all options we ... http://sitepoint.com/jquery-select-box-components-chosen-vs-select2.
Read more >
Examples - Select2 - JeeSite
You can, and should, use a <label> with Select2, just like any other <select> element. Click this to focus the single select element....
Read more >
Working with Select elements and Select2 widgets in Cypress
Single value select element ... Let's take a page where a user selects a single state from a list of choices. Maybe it...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found