Appearance
ComboBox API Reference
Complete API documentation for the ComboBox component.
Props
Core Functionality
| Prop | Type | Default | Description |
|---|---|---|---|
items | Array | [] | Array of items to display in the dropdown |
modelValue | String/Number/Array/Object | null | The selected value(s). Use with v-model |
multiple | Boolean | false | Enable multiple selection mode |
Item Configuration
| Prop | Type | Default | Description |
|---|---|---|---|
itemText | String | 'text' | Property name to use for item display text |
itemValue | String | 'value' | Property name to use for item value |
itemDisabled | String | 'disabled' | Property name to check if item is disabled |
Filtering & Sorting
| Prop | Type | Default | Description |
|---|---|---|---|
filterFunction | Function | null | Custom filter function (item, searchText) => Boolean |
selectedOnTop | Boolean | false | Show selected items at the top of the list |
Menu Configuration
| Prop | Type | Default | Description |
|---|---|---|---|
placement | String | 'bottom' | Menu placement: 'top', 'bottom' |
offset | Array | [0, 0.125] | Offset from trigger [x, y] in rem |
menuWidth | String/Number | null | Custom menu width (px or string with units) |
matchTriggerWidth | Boolean | true | Match menu width to trigger width |
Input Configuration
| Prop | Type | Default | Description |
|---|---|---|---|
placeholder | String | '' | Input placeholder text |
disabled | Boolean | false | Disable the combobox |
loading | Boolean | false | Show loading state |
clearable | Boolean | false | Show clear button when there's a selection |
readonly | Boolean | false | Make input readonly (menu won't open) |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue | value | Emitted when selection changes. Use with v-model |
change | value | Emitted when selection changes (same as update:modelValue) |
select | item, value | Emitted when an item is selected from the dropdown |
remove | item, value | Emitted when an item is removed (multiple mode) |
search | searchText | Emitted when search text changes |
create | item, value | Emitted when a custom item is created by typing |
Event Examples
vue
<template>
<OComboBox
v-model="selected"
:items="items"
@select="handleSelect"
@create="handleCreate"
@search="handleSearch"
/>
</template>
<script setup>
const handleSelect = (item, value) => {
console.log('Selected item:', item);
console.log('Selected value:', value);
};
const handleCreate = (item, value) => {
console.log('Created custom item:', item);
console.log('Custom value:', value);
// You can save custom items to your backend here
};
const handleSearch = (searchText) => {
console.log('Searching for:', searchText);
// Perform async search if needed
};
</script>Slots
| Slot | Props | Description |
|---|---|---|
no-data | - | Custom content to display when no items are available |
Slot Examples
vue
<template>
<OComboBox v-model="selected" :items="items">
<template #no-data>
<div class="custom-empty">
<p>No options found</p>
<button @click="loadMore">Load More</button>
</div>
</template>
</OComboBox>
</template>Methods
Methods exposed via template ref:
| Method | Parameters | Returns | Description |
|---|---|---|---|
focus() | - | void | Focus the input field |
blur() | - | void | Blur the input field |
openMenu() | - | void | Open the dropdown menu |
closeMenu() | - | void | Close the dropdown menu |
search(value) | String | void | Set the search text programmatically |
Method Examples
vue
<template>
<div>
<OComboBox ref="comboboxRef" v-model="selected" :items="items" />
<button @click="focusComboBox">Focus</button>
<button @click="openMenu">Open Menu</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const comboboxRef = ref(null);
const focusComboBox = () => {
comboboxRef.value.focus();
};
const openMenu = () => {
comboboxRef.value.openMenu();
};
</script>TypeScript Types
typescript
interface ComboBoxItem {
text: string;
value: any;
disabled?: boolean;
[key: string]: any;
}
type ComboBoxValue = string | number | Array<string | number> | object | null;
type FilterFunction = (item: ComboBoxItem, searchText: string) => boolean;
type Placement = 'top' | 'bottom';Usage Patterns
Single Selection with Custom Values
vue
<template>
<OComboBox
v-model="country"
:items="countries"
placeholder="Select or type a country..."
/>
</template>
<script setup>
import { ref } from 'vue';
const country = ref(null);
const countries = ref([
{ text: 'United States', value: 'us' },
{ text: 'United Kingdom', value: 'uk' },
{ text: 'Canada', value: 'ca' },
]);
</script>Multiple Selection (Tags)
vue
<template>
<OComboBox
v-model="tags"
:items="suggestions"
:multiple="true"
placeholder="Type tags and press Enter..."
@create="handleCreateTag"
/>
</template>
<script setup>
import { ref } from 'vue';
const tags = ref([]);
const suggestions = ref([
{ text: 'Vue', value: 'vue' },
{ text: 'React', value: 'react' },
{ text: 'Angular', value: 'angular' },
]);
const handleCreateTag = (item, value) => {
console.log('New tag created:', value);
// Optionally save to backend
};
</script>With Custom Filter
vue
<template>
<OComboBox
v-model="selected"
:items="products"
:filter-function="customFilter"
placeholder="Search products..."
/>
</template>
<script setup>
import { ref } from 'vue';
const selected = ref(null);
const products = ref([
{ text: 'Laptop', value: 'laptop', category: 'electronics' },
{ text: 'Phone', value: 'phone', category: 'electronics' },
{ text: 'Desk', value: 'desk', category: 'furniture' },
]);
const customFilter = (item, searchText) => {
const text = item.text.toLowerCase();
const category = item.category.toLowerCase();
const search = searchText.toLowerCase();
return text.includes(search) || category.includes(search);
};
</script>Email Input Example
vue
<template>
<OComboBox
v-model="emails"
:items="emailSuggestions"
:multiple="true"
placeholder="Enter email addresses..."
@create="validateEmail"
/>
</template>
<script setup>
import { ref } from 'vue';
const emails = ref([]);
const emailSuggestions = ref([
{ text: 'john@example.com', value: 'john@example.com' },
{ text: 'jane@example.com', value: 'jane@example.com' },
]);
const validateEmail = (item, value) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
alert('Invalid email address');
// Remove invalid email
emails.value = emails.value.filter(e => e !== value);
}
};
</script>Keyboard Shortcuts
| Key | Action |
|---|---|
Enter | Create custom entry from typed text |
Backspace | Remove last selected item (multiple, empty input) |
Shift/Ctrl/Cmd + Backspace | Remove all selected items (multiple mode) |
Escape | Close the dropdown menu |
| Click outside | Close menu and commit typed text (single mode) |
Styling
The component uses scoped styles with the following main classes:
.combobox- Root container.trigger-container- Input trigger area.combobox-input- The input field.combobox-dropdown- Dropdown menu container.select-option- Individual option item.option-checkbox- Checkbox for multiple selection.clear-button- Clear selection button.select-arrow- Dropdown arrow icon
Custom Styling Example
vue
<style>
.combobox {
/* Custom styles */
}
.combobox .trigger-container {
border-radius: 8px;
border-color: #3b82f6;
}
.combobox .combobox-input {
font-size: 1.125rem;
}
</style>Best Practices
- Use for flexible input: Use ComboBox when users need both predefined options and custom entries
- Provide suggestions: Always provide relevant suggestions in the
itemsprop - Handle create event: Listen to the
createevent to validate or save custom entries - Single vs Multiple: Use single mode for single-value fields, multiple mode for tags/lists
- Validation: Implement validation in the
createevent handler for custom entries - Clearable: Enable
clearablefor better UX when values can be optional - Loading state: Use the
loadingprop during async operations - Accessible placeholders: Provide clear placeholder text that describes what users can do
Accessibility
The component follows accessibility best practices:
- Keyboard navigation support
- Focus management
- ARIA attributes for screen readers
- Clear visual states (focus, hover, disabled)
- Semantic HTML structure
Performance Tips
- Large datasets: For very large item lists, consider implementing virtual scrolling
- Async search: Use the
searchevent to implement server-side filtering - Debouncing: Debounce the
searchevent for async operations - Custom filter: Use custom filter functions for complex filtering logic