💡 A lightweight and flexible Vue 2 & Vue 3 wrapper for Choices.js, fully compatible with Bootstrap 5 and written in TypeScript. Supports CDN and bundled usage, v-model binding, custom events, async search, and multiple selection modes — all without relying on jQuery.
npm install choices-vue3
<link href="https://cdn.jsdelivr.net/npm/choices-vue3@1.0.0/dist/choices-vue3.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/choices-vue3@1.0.0/dist/choices-vue3.min.js"></script>
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { useChoices } from 'choices-vue3'
import 'choices-vue3/dist/vue3/choices-vue3.css'
const app = createApp(App)
app.use(useChoices)
app.mount('#app')
as a component? Or for TypeScript when build (Tested in Vite when using npm run build
):
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { ChoicesVue3 } from 'choices-vue3/vue3' or import ChoicesVue3 from 'choices-vue3/vue3'
import 'choices-vue3/dist/vue3/choices-vue3.css'
const app = createApp(App)
app.component('choices-vue3', ChoicesVue3)
app.mount('#app')
Now use in your any components:
<template>
<choices-vue3
v-model="selectedValue"
:options="selectOptions"
@change="handleChange"
class="mb-2"
:placeholder="'Select an option'"
></choices-vue3>
</template>
<script setup>
import { ref } from 'vue'
const selectedValue = ref(null)
const selectOptions = ref([
{ value: '1a2b3c4d', label: 'Admin - Budi Santoso' },
{ value: '2b3c4d5e', label: 'Marketing - Siti Aminah' },
{ value: '3c4d5e6f', label: 'Developer - Agus Wijaya' },
{ value: '4d5e6f7g', label: 'HR - Indah Permata' },
{ value: '5e6f7g8h', label: 'Finance - Rudi Hartono' },
{ value: '6f7g8h9i', label: 'QA - Tono Supriyadi' },
{ value: '7g8h9i0j', label: 'Design - Sarah Maharani' },
{ value: '8h9i0j1k', label: 'Support - Dimas Ananta' },
{ value: '9i0j1k2l', label: 'PM - Citra Larasati' },
{ value: '0j1k2l3m', label: 'Intern - Yoga Pranata' },
])
</script>
Or you can use TypeScript:
<template>
<choices-vue3
v-model="selectedValue"
:options="selectOptions"
@change="handleChange"
class="mb-2"
:placeholder="'Select an option'"
></choices-vue3>
/>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
name: 'HelloWorld',
setup() {
const selectedValue = ref('')
const selectOptions = ref([
{ value: '1a2b3c4d', label: 'Admin - Budi Santoso' },
{ value: '2b3c4d5e', label: 'Marketing - Siti Aminah' },
{ value: '3c4d5e6f', label: 'Developer - Agus Wijaya' },
{ value: '4d5e6f7g', label: 'HR - Indah Permata' },
{ value: '5e6f7g8h', label: 'Finance - Rudi Hartono' },
{ value: '6f7g8h9i', label: 'QA - Tono Supriyadi' },
{ value: '7g8h9i0j', label: 'Design - Sarah Maharani' },
{ value: '8h9i0j1k', label: 'Support - Dimas Ananta' },
{ value: '9i0j1k2l', label: 'PM - Citra Larasati' },
{ value: '0j1k2l3m', label: 'Intern - Yoga Pranata' },
])
return {
selectedValue,
selectOptions,
}
}
})
</script>
<template>
<choices-vue3
v-model="selectedValue"
:options="selectOptions"
@change="handleChange"
class="mb-2"
:placeholder="'Select an option'"
:config="{ mode: 'multiple', delimiter: ',', removeItemButton: true, removeItems: true, setting: { returnObject: false }}"
:multiple="true"
></choices-vue3>
</template>
<script setup>
import { ref } from 'vue'
const selectedValue = ref(null)
const selectOptions = ref([
{ value: '1a2b3c4d', label: 'Admin - Budi Santoso' },
{ value: '2b3c4d5e', label: 'Marketing - Siti Aminah' },
{ value: '3c4d5e6f', label: 'Developer - Agus Wijaya' },
{ value: '4d5e6f7g', label: 'HR - Indah Permata' },
{ value: '5e6f7g8h', label: 'Finance - Rudi Hartono' },
{ value: '6f7g8h9i', label: 'QA - Tono Supriyadi' },
{ value: '7g8h9i0j', label: 'Design - Sarah Maharani' },
{ value: '8h9i0j1k', label: 'Support - Dimas Ananta' },
{ value: '9i0j1k2l', label: 'PM - Citra Larasati' },
{ value: '0j1k2l3m', label: 'Intern - Yoga Pranata' },
])
</script>
Or you can use TypeScript:
<template>
<choices-vue3
v-model="selectedValue"
:options="selectOptions"
@change="handleChange"
class="mb-2"
:placeholder="'Select an option'"
:config="{ mode: 'multiple', delimiter: ',', removeItemButton: true, removeItems: true, setting: { returnObject: true }}"
:multiple="true"
></choices-vue3>
/>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
name: 'HelloWorld',
setup() {
const selectedValue = ref('')
const selectOptions = ref([
{ value: '1a2b3c4d', label: 'Admin - Budi Santoso' },
{ value: '2b3c4d5e', label: 'Marketing - Siti Aminah' },
{ value: '3c4d5e6f', label: 'Developer - Agus Wijaya' },
{ value: '4d5e6f7g', label: 'HR - Indah Permata' },
{ value: '5e6f7g8h', label: 'Finance - Rudi Hartono' },
{ value: '6f7g8h9i', label: 'QA - Tono Supriyadi' },
{ value: '7g8h9i0j', label: 'Design - Sarah Maharani' },
{ value: '8h9i0j1k', label: 'Support - Dimas Ananta' },
{ value: '9i0j1k2l', label: 'PM - Citra Larasati' },
{ value: '0j1k2l3m', label: 'Intern - Yoga Pranata' },
])
return {
selectedValue,
selectOptions,
}
}
})
</script>
<template>
<choices-vue3
v-model="selectedValue"
:options="selectOptions"
@change="handleChange"
class="mb-2"
:placeholder="'Select an option'"
:config="{ mode: 'tagging', delimiter: ',', removeItemButton: true, removeItems: true, setting: { returnObject: false }}"
:multiple="true"
></choices-vue3>
</template>
<script setup>
import { ref } from 'vue'
const selectedValue = ref(null)
const selectOptions = ref([])
</script>
Or you can use TypeScript:
<template>
<choices-vue3
v-model="selectedValue"
:options="selectOptions"
@change="handleChange"
class="mb-2"
:placeholder="'Select an option'"
:config="{ mode: 'tagging', delimiter: ',', removeItemButton: true, removeItems: true, setting: { returnObject: true }}"
:multiple="true"
></choices-vue3>
/>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
name: 'HelloWorld',
setup() {
const selectedValue = ref(null)
const selectOptions = ref([])
return {
selectedValue,
selectOptions,
}
}
})
</script>
Prop | Type | Default | Required | Description |
---|---|---|---|---|
id |
String |
'choices' |
✘ | The ID attribute for the main element |
name |
String |
'choices' |
✘ | The name attribute for form input |
options |
Array |
— | ✔ | List of available options |
modelValue |
String | Number | Array
|
null |
✘ | Selected value (used with v-model ) |
placeholder |
String |
'Select an option' |
✘ | Placeholder text when no option is selected |
multiple |
Boolean |
false |
✘ | Enables multiple selection |
disabled |
Boolean |
false |
✘ | Disables the component |
required |
Boolean |
false |
✘ | Marks the field as required |
valueKey |
String |
'value' |
✘ | Key used to extract value from option object |
textKey |
String |
'label' |
✘ | Key used to extract display text from option object |
config |
Object |
() => ({}) |
✘ | Additional configuration options |
fetchOnSearch |
Boolean |
false |
✘ | Emits search event on user input |
loadingSelect |
Boolean |
undefined |
✘ | Shows loading indicator when true |
Event | Payload | Description |
---|---|---|
update:modelValue |
String | Number | Array
|
Emitted when the selected value changes |
change |
Selected option(s) | Emitted when an option is selected |
search |
String |
Emitted when the user types in the input field |
loadMore |
— | Emitted to load more data (e.g., for infinite scrolling) |
The config
prop allows you to customize the behavior of the select component. Below are the guidelines for using it in different modes:
- You do not need to set
multiple
. - The
config
prop is optional. - Example (with optional features enabled):
<MySelect
:config="{
removeItemButton: true,
removeItems: true,
setting: { returnObject: false }
}"
/>
- You must set
multiple
totrue
. - You must provide a valid
config
withmode
set to either'multiple'
or'tagging'
.
<MySelect
multiple
:config="{
mode: 'multiple',
delimiter: ',',
removeItemButton: true,
removeItems: true,
setting: { returnObject: false }
}"
/>
<MySelect
multiple
:config="{
mode: 'tagging',
delimiter: ',',
removeItemButton: true,
removeItems: true,
setting: { returnObject: false }
}"
/>
Inside config.setting
, the returnObject
option controls what value gets emitted and bound via v-model
:
Setting | Behavior |
---|---|
returnObject: false |
Emits only the value from the selected item (based on valueKey ). |
returnObject: true |
Emits the entire object of the selected item. Useful when you need access to more fields. |
// Given options:
[
{ label: 'Apple', value: 'apple', category: 'fruit' },
{ label: 'Carrot', value: 'carrot', category: 'vegetable' }
]
// With returnObject: false
modelValue === 'apple'
// With returnObject: true
modelValue === { label: 'Apple', value: 'apple', category: 'fruit' }
Make sure you choose the returnObject
behavior based on whether your app needs only the value or the entire item object.
I'm a full stack developer...