Appearance
Multiselect Component
A customizable, feature-rich dropdown select component that replaces external multiselect packages. Supports single selection, multiple selection, tagging, autocomplete search, grouping, custom styling, lazy loading, and debounce search.
Table of Contents
Import
ts
import { Multiselect } from "dolphin-components";
import type { MultiselectProps, MultiselectOption } from "dolphin-components";Props
| Prop Name | Type | Default | Description |
|---|---|---|---|
modelValue | any | [] | Selected option(s). Can be an object, string, or array. |
options | MultiselectOption[] | - | Array of available options. |
multiple | boolean | false | Enable multiple selections. |
searchable | boolean | true | Show search input field for filtering options. |
placeholder | string | "Select option" | Placeholder text when empty. |
disabled | boolean | false | Disable interactions. |
loading | boolean | false | Show built-in spinner. |
label | string | - | Key to use as label when options are objects. |
trackBy | string | - | Key to track option identity (needed for objects). |
allowEmpty | boolean | true | Allow clearing selection entirely. |
closeOnSelect | boolean | true | Automatically close dropdown after selection. |
hideSelected | boolean | false | Hide selected options from the dropdown list. |
taggable | boolean | false | Allow user to create custom tags. |
tagPlaceholder | string | "Press enter to create a tag" | Placeholder shown when entering a new tag. |
tagPosition | "top" | "bottom" | "top" | Position of the custom tag in suggestions. |
groupValues | string | - | Property key containing nested group option arrays. |
groupLabel | string | - | Property key representing group labels. |
groupSelect | boolean | false | Allow clicking a group label to select/deselect the whole group. |
maxHeight | number | 300 | Maximum height in pixels of the options dropdown. |
limit | number | 99999 | Maximum number of tags visible in display field before truncating. |
limitText | (count: number) => string | and X more | Formatter function for truncated items. |
debounceSearch | boolean | false | Debounce the search-change emission. |
debounceSecond | number | 3 | Seconds to debounce search inputs. |
useTeleport | boolean | false | Teleport dropdown menu to target container. |
teleportTarget | string | object | "body" | Teleport destination element selector. |
Emitted Events
| Event Name | Payload | Description |
|---|---|---|
update:modelValue | any | Emitted when value is selected/removed (supports v-model). |
select | (option, id) | Emitted when an option is selected. |
remove | (option, id) | Emitted when an option is deselected. |
tag | (label, id) | Emitted when a new tag is created. |
open | (id) | Emitted when dropdown opens. |
close | (value, id) | Emitted when dropdown closes. |
search-change | (query) | Emitted when user types in search input. |
Slots
| Slot Name | Scope Parameters | Description |
|---|---|---|
caret | toggle | Custom caret dropdown button. |
clear | search | Element to clear selection/search. |
selection | search, remove, values, isOpen | Custom display area for selected tags/values. |
tag | option, search, remove | Custom tag elements layout. |
option | option, search, index | Custom item layout in suggestions dropdown. |
noResult | search | Content to show when search returns zero results. |
noOptions | - | Content to show when options list is empty. |
Usage Examples
1. Basic Single Select
vue
<template>
<Multiselect
v-model="selectedUser"
:options="users"
label="name"
trackBy="id"
placeholder="Select a manager"
/>
</template>
<script setup>
import { ref } from "vue";
import { Multiselect } from "dolphin-components";
const selectedUser = ref(null);
const users = ref([
{ id: 101, name: "Alice Smith" },
{ id: 102, name: "Bob Jones" },
{ id: 103, name: "Charlie Miller" },
]);
</script>2. Multi-Select with Search Limit
vue
<template>
<Multiselect
v-model="selectedTechs"
:options="technologies"
:multiple="true"
:closeOnSelect="false"
:limit="3"
placeholder="Choose your tech stack"
/>
</template>
<script setup>
import { ref } from "vue";
import { Multiselect } from "dolphin-components";
const selectedTechs = ref([]);
const technologies = ref([
"Vue",
"React",
"TypeScript",
"Node.js",
"Vite",
"TailwindCSS",
]);
</script>3. Option Grouping
vue
<template>
<Multiselect
v-model="selectedDrink"
:options="menu"
groupValues="items"
groupLabel="category"
:groupSelect="true"
label="name"
trackBy="id"
placeholder="Choose a beverage"
/>
</template>
<script setup>
import { ref } from "vue";
import { Multiselect } from "dolphin-components";
const selectedDrink = ref(null);
const menu = ref([
{
category: "Hot Drinks",
items: [
{ id: 1, name: "Espresso" },
{ id: 2, name: "Green Tea" },
],
},
{
category: "Cold Drinks",
items: [
{ id: 3, name: "Iced Latte" },
{ id: 4, name: "Lemonade" },
],
},
]);
</script>TypeScript Interfaces
typescript
interface MultiselectOption {
[key: string]: any;
}
interface MultiselectProps {
modelValue: any;
options: MultiselectOption[];
multiple?: boolean;
searchable?: boolean;
placeholder?: string;
disabled?: boolean;
loading?: boolean;
label?: string;
trackBy?: string;
allowEmpty?: boolean;
closeOnSelect?: boolean;
hideSelected?: boolean;
taggable?: boolean;
tagPlaceholder?: string;
tagPosition?: "top" | "bottom";
groupValues?: string;
groupLabel?: string;
groupSelect?: boolean;
maxHeight?: number;
limit?: number;
limitText?: (count: number) => string;
debounceSearch?: boolean;
debounceSecond?: number;
useTeleport?: boolean;
teleportTarget?: string | object;
}Styling Notes
The component relies on .multiselect classes. It integrates with the standard input validation state:
- When using the
v-input-errordirective, if there is a validation error, the container's.multiselect__tagselement will automatically receive the.input-errorclass, highlighting its border in red.
Best Practices
- Always use
labelandtrackByfor object options — Without these, the component can't identify or display options. - Use
closeOnSelect="false"for multi-select — Keeps the dropdown open for selecting multiple items in succession. - Use
debounceSearchfor API-backed search — Prevents rapid-fire API calls while the user types. - Set reasonable
limitvalues — Controls how many selected tags are visible before showing a "+X more" badge. - Use
useTeleportinside scrollable containers — Prevents the dropdown from being clipped by parentoverflow: hidden.
Troubleshooting
Dropdown not opening
- Check that
disabledis not set totrue. - Ensure the
optionsarray is populated.
Selected value not displaying
- Verify that
labelpoints to the correct property on your option objects. - Ensure
trackByis set when using object options.
Dropdown clipped by parent container
- Use
:useTeleport="true"andteleportTarget="body"to render the dropdown outside the parent container.