0.1.3 • Published 10 months ago

@loop8/vue-select v0.1.3

Weekly downloads
-
License
MIT
Repository
bitbucket
Last release
10 months ago

Vue Loop8 Select

A Vue 3 select component inspired by Select2, built using the Composition API.

Features

  • Single and multiple select support
  • Search/filtering capabilities
  • Remote data loading via AJAX
  • Infinite scrolling pagination for large datasets
  • Custom templates with slots for rich display options
  • Keyboard navigation
  • Customizable via props
  • No jQuery dependency
  • Form integration with standard HTML form elements
  • Fully compatible with Vue 3 and the Composition API
  • Works with v-model for two-way binding

Installation

npm install @loop8/vue-select
# or
yarn add @loop8/vue-select

Importing Styles

After installing the package, you need to import the required CSS files in your main entry file (usually main.js or main.ts):

// Import the component styles
import '@loop8/vue-select/src/styles/loop-select.css';
import '@loop8/vue-select/src/styles/spinner.css';

The styles are modular and can be customized by overriding the CSS classes. For complete styling documentation and available CSS classes, see the Usage Guide.

Styling and Customization

Loop8Select is designed to be easily customized:

  • Uses global, non-scoped CSS classes that are simple to override
  • Provides slots for custom option and selection templates
  • Supports custom loading indicators
  • Can be themed for light/dark modes or to match your application design by overriding CSS classes
<!-- Basic usage -->
<Loop8Select
  v-model="selected"
  :options="options"
/>

For complete styling documentation and available CSS classes, see the Usage Guide.

Usage

Global Registration

import { createApp } from 'vue';
import Loop8Select from '@loop8/vue-select';
import App from './App.vue';

const app = createApp(App);
app.use(Loop8Select);
app.mount('#app');

Local Registration

<template>
  <div>
    <Loop8Select
      v-model="selected"
      :options="options"
      :multiple="false"
      name="my-select"
      placeholder="Select an option"
    />
  </div>
</template>

<script>
import { ref } from 'vue';
import { Loop8Select } from '@loop8/vue-select';

export default {
  components: {
    Loop8Select
  },
  setup() {
    const selected = ref(null);
    const options = ref([
      { value: 1, text: 'Option 1' },
      { value: 2, text: 'Option 2' },
      { value: 3, text: 'Option 3' }
    ]);

    return {
      selected,
      options
    };
  }
};
</script>

With AJAX Data Loading

<template>
  <Loop8Select
    v-model="selected"
    :options="[]"
    :ajax="ajaxConfig"
    valueKey="id"
    labelKey="name"
    name="ajax-select"
    placeholder="Search..."
  />
</template>

<script>
import { ref } from 'vue';
import { Loop8Select, Loop8SelectAjaxConfig } from '@loop8/vue-select';

export default {
  components: { Loop8Select },
  setup() {
    const selected = ref(null);
    
    const ajaxConfig = {
      url: 'https://api.example.com/search',
      method: 'GET',
      minimumInputLength: 2,
      processResults: (data) => {
        return {
          results: data.items,
          more: false
        };
      }
    };
    
    return { 
      selected, 
      ajaxConfig 
    };
  }
};
</script>

With Infinite Scrolling Pagination

<template>
  <Loop8Select
    v-model="selected"
    :options="[]"
    :ajax="paginationConfig"
    valueKey="id"
    labelKey="name"
    name="paginated-select"
    placeholder="Search with infinite scrolling..."
  />
</template>

<script>
import { ref } from 'vue';
import { Loop8Select } from '@loop8/vue-select';

export default {
  components: { Loop8Select },
  setup() {
    const selected = ref(null);
    
    const paginationConfig = {
      url: 'https://api.example.com/search',
      pagination: true,
      limit: 20,
      processResults: (data) => {
        return {
          results: data.items,
          more: data.has_more // true if there are more results
        };
      }
    };
    
    return { selected, paginationConfig };
  }
};
</script>

With Custom Templates

<template>
  <Loop8Select v-model="selectedCountry" :options="countries" valueKey="code" labelKey="name">
    <!-- Custom option template -->
    <template #option="{ option, selected, highlighted }">
      <div class="country-option" :class="{ selected, highlighted }">
        <span class="flag">{{ option.flag }}</span>
        <span class="name">{{ option.name }}</span>
        <span class="region">{{ option.region }}</span>
      </div>
    </template>
    
    <!-- Custom selected option template -->
    <template #selected-option="{ option }">
      <div class="selected-country">
        <span class="flag">{{ option.flag }}</span>
        <span class="name">{{ option.name }}</span>
      </div>
    </template>
  </Loop8Select>
</template>

<script>
import { ref } from 'vue';
import { Loop8Select } from '@loop8/vue-select';

export default {
  components: { Loop8Select },
  setup() {
    const selectedCountry = ref(null);
    const countries = ref([
      { code: 'FI', name: 'Finland', flag: '🇫🇮', region: 'Europe' },
      { code: 'US', name: 'United States', flag: '🇺🇸', region: 'North America' },
      { code: 'DE', name: 'Germany', flag: '🇩🇪', region: 'Europe' },
      { code: 'JP', name: 'Japan', flag: '🇯🇵', region: 'Asia' }
    ]);
    
    return { selectedCountry, countries };
  }
};
</script>

With Array Values

<template>
  <Loop8Select
    v-model="selected"
    :options="['Option 1', 'Option 2', 'Option 3']"
    name="simple-select"
  />
</template>

<script>
import { ref } from 'vue';
import { Loop8Select } from '@loop8/vue-select';

export default {
  components: { Loop8Select },
  setup() {
    const selected = ref(null);
    return { selected };
  }
};
</script>

Multiple Select

<template>
  <Loop8Select
    v-model="selectedItems"
    :options="options"
    :multiple="true"
    name="multi-select"
  />
</template>

<script>
import { ref } from 'vue';
import { Loop8Select } from '@loop8/vue-select';

export default {
  components: { Loop8Select },
  setup() {
    const selectedItems = ref([]);
    const options = ref([
      { value: 1, text: 'Option 1' },
      { value: 2, text: 'Option 2' },
      { value: 3, text: 'Option 3' }
    ]);

    return {
      selectedItems,
      options
    };
  }
};
</script>

Props

PropTypeDefaultDescription
modelValueAnynullThe selected value(s), used with v-model
optionsArray[]Array of options to select from (objects or primitive values)
placeholderString'Select an option'Placeholder text to display when no option is selected
multipleBooleanfalseAllow multiple selections
disabledBooleanfalseDisable the select component
requiredBooleanfalseMark the select as required for form validation
nameString''Name attribute for the hidden select element (for form submission)
loadingBooleanfalseShow loading state
valueKeyString'value'Key to use for option values when using object options
labelKeyString'text'Key to use for option labels when using object options
ajaxObjectnullConfiguration for AJAX data loading and initial value resolution

Slots

SlotScopeDescription
option{ option, selected, highlighted, index }Template for rendering dropdown options
selected-option{ option, remove }Template for rendering selected items
loading-morenoneTemplate for the "loading more" indicator

Events

EventDescription
update:modelValueEmitted when the selection changes, provides the selected value(s)
update:selectedOptionsEmitted when the selection changes, provides the full selected option object(s) including labels and other data
invalid-optionEmitted when an invalid option is detected. For single select, provides the invalid value. For multiple select, provides an array of invalid values. The component automatically removes invalid values from the selection.

Example: Using selectedOptions

<template>
  <Loop8Select
    v-model="selectedValue"
    @update:selectedOptions="handleSelectedOptions"
    :options="options"
  />
  <div v-if="selectedOption">
    Selected: {{ selectedOption.text }}
  </div>
</template>

<script>
import { ref } from 'vue';
import { Loop8Select } from '@loop8/vue-select';

export default {
  components: { Loop8Select },
  setup() {
    const selectedValue = ref(null);
    const selectedOption = ref(null);
    
    const options = ref([
      { value: 1, text: 'Option 1' },
      { value: 2, text: 'Option 2' },
      { value: 3, text: 'Option 3' }
    ]);
    
    const handleSelectedOptions = (option) => {
      selectedOption.value = option;
    };
    
    return {
      selectedValue,
      selectedOption,
      options,
      handleSelectedOptions
    };
  }
};
</script>

License

MIT