Code Monkey home page Code Monkey logo

vue-listbox-multiselect's Introduction

Vue Dual Listbox MultiSelect Dropdown Component

@banneredge/vue-listbox-multiselect

Total Downloads Latest Release License

Preview

Demo

http://vue-listbox-multiselect.s3-website-us-west-2.amazonaws.com

Motivation

There are several good multi-select components available for Vue. However, none are suitable for enterprise app development. In a typical enterprise app, you are often challenged offering a simple drop-down which allows the user to filter through thousands of categorized items from the server, and allows the user to select hundreds. At Banner Edge Media, we have been using a similar component for multiple years. As we migrate to Vue, we wanted to share this component with the Vue community, and together make it even better.

Setup

Note: This component assumes you have Vuetify installed. If you are starting a new project and want to use Vuetify, please follow their set-up guide: https://vuetifyjs.com/en/getting-started/quick-start/

Install:

# NPM
npm install @banneredge/vue-listbox-multiselect

# CDN
<script src='https://unpkg.com/@banneredge/vue-listbox-multiselect'></script>

Usage:

<script lang="ts">
import Vue from 'vue';
import VueListboxMultiselect from '@banneredge/vue-listbox-multiselect';
import dataSet from './usCities';

export default Vue.extend({
  name: 'ServeDev',
  components: {
    VueListboxMultiselect
  },
  data() {
    return {
      selectedList: [] as any[],
    };
  },
  methods: {
    async search(query: string): Promise<any[]> {
      const ids = this.selectedList.map((x) => x.id);
      let subset = dataSet.filter((x) => !ids.includes(`${x.state}-${x.city}`));

      if (!query) {
        subset = subset.slice(0, 100);
      } else {
        const q = query.toLowerCase();
        subset = subset.filter((x) => x.city.toLowerCase().includes(q) || x.state.toLowerCase().includes(q));
        subset = subset.slice(0, 100);
      }

      return subset.map((x: any) => {
        return {
          id: `${x.state}-${x.city}`,
          value: x.city,
          group: x.state
        }
      });
    },
  },
});
</script>

<template>
  <v-app id="app">
    <link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
    <vue-listbox-multiselect
        v-model="selectedList"
        :search-function="search"
        placeholder="Search Items"
        style="width: 300px; margin: 20px auto"
        size="medium"
        :hide-search="false"
    />
  </v-app>
</template>

Notes:

  • The current version is heavily dependent on Vuetify with mdi icons for the arrows
  • There is no direct way to pass in the items, everything must go through the async search function. The function will get called with a blank query on load.
  • You must implement your own limit, filtering and excluding selected items (See examples). This is set up because we assume most use-cases will be calling the server for data and that will need to be handled on the server.
  • There is lots of room for improvement, so please check out the Roadmap and contribute!
  • Current recommendation is to pull 100 results with each query. Users do not need to scroll through more, they can just search to get what they need.

Props

Prop Description
v-model Model to bind output to. You can set it initially to pre-select items. Note: you will need to exclude selected items from each query. Type: {id: string, value: string, group?: string}. The component will NOT watch for changes on the model and re-fresh the list.
:search-function Function that will get called when the component needs data. It should be async or return a Promise. A string query will be passed in as the only parameter. While the promise is not fulfilled, a loading indicator will show.
placeholder Text to show in the select field when no items are selected. Defaults to 'None'
size How wide to expand the menu. Options are, null, medium, large, x-large. They will fall back on a size that fits. Default size is 366px wide, it will look good in most modern mobile devices.
hide-search Hides the search bar. Search is on by default. If you have a small list and still want to use this component, you have the option to turn it off. You can also turn it off dynamically if items < 10 for example.

Roadmap

  • Add demo static site.
  • Clean up the code a bit and add comments.
  • Add interfaces for parameters
    • We should add a few more features before making contracts
  • Speed it up
    • It gets a little slow when you have 1000 items, and you have to group and sort them
    • Keeping the limit to 100 makes it work well.
  • Test browser compatibility.
    • Seems to work well in Chrome, Firefox, Edge
    • We should establish what we support.
  • Remove Vuetify dependency
    • Vuetify provides some very cool pre-made components, but we want this to be usable with any library.
  • Figure out a smart way to do widths.
    • Sometimes if we have a large monitor and long item names, we want to stretch it very wide. If the item names are not long it does not look good.
  • Add a prop to Hide Search (May want to keep it for all use-cases?)
    • Sometimes we want to use this with a very small list and don't need the search box.
  • Add test coverage?
  • Add a way to reset it to original state dynamically
    • Reset selected list
    • Re-run blank query
    • Through Emitter?
  • Add slots to make it fully customizable
  • Add more input interactions
    • Currently Supported:
      • Click (Select)
      • Ctrl-Click (Select Multiple)
      • Double-Click (Move Item)
    • Needed:
      • Shift-Click
      • Ctrl-A ?
      • Move with arrow keys?
      • Shift-arrow keys?

vue-listbox-multiselect's People

Contributors

alexviderman avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.