Forms
Searchable select
Implement the searchable combobox with complete Boobstrap JS, Alpine.js, and React examples.
Forms
Searchable select
The combobox filters human-readable labels while synchronizing the selected machine value into a hidden form input.
Boobstrap JavaScript
HTML · Complete Boobstrap JS markup
<form>
<div class="bs-form-group">
<label class="bs-label" for="team-role">Team role</label>
<div class="bs-combobox" data-bs-combobox>
<input
class="bs-combobox-input"
id="team-role"
data-bs-combobox-input
placeholder="Search roles"
/>
<button
class="bs-combobox-toggle"
type="button"
data-bs-combobox-toggle
aria-label="Toggle roles"
></button>
<input type="hidden" name="team_role" data-bs-combobox-value />
<div class="bs-combobox-listbox" data-bs-combobox-listbox hidden>
<div class="bs-combobox-option" data-bs-combobox-option data-bs-value="designer">
Designer
</div>
<div class="bs-combobox-option" data-bs-combobox-option data-bs-value="engineer">
Engineer
</div>
<div class="bs-combobox-option" data-bs-combobox-option data-bs-value="product-manager">
Product manager
</div>
<div class="bs-combobox-option" data-bs-combobox-option data-bs-value="founder">
Founder
</div>
<div class="bs-combobox-empty" data-bs-combobox-empty hidden>
No roles found
</div>
</div>
</div>
</div>
</form>JavaScript · Initialize only comboboxes
import "@boobstrap/boobstrap";
import { initComboboxes } from "@boobstrap/boobstrap/js/combobox";
const comboboxes = initComboboxes(document);
// Call this from your router or view cleanup hook.
export function destroyComboboxes() {
comboboxes.forEach((combobox) => combobox.destroy());
}Alpine.js
JavaScript · Alpine setup
import "@boobstrap/boobstrap";
import Alpine from "alpinejs";
import boobstrap from "@boobstrap/alpine";
Alpine.plugin(boobstrap);
Alpine.start();HTML · Complete Alpine combobox
<form>
<div class="bs-form-group">
<label class="bs-label" for="alpine-role">Team role</label>
<div class="bs-combobox" x-data="bsCombobox" x-bind="root">
<input
class="bs-combobox-input"
id="alpine-role"
x-bind="input"
data-bs-combobox-input
placeholder="Search roles"
/>
<button
class="bs-combobox-toggle"
x-bind="toggleButton"
data-bs-combobox-toggle
aria-label="Toggle roles"
></button>
<input type="hidden" name="team_role" data-bs-combobox-value />
<div
class="bs-combobox-listbox"
x-bind="listbox"
data-bs-combobox-listbox
hidden
>
<div
class="bs-combobox-option"
x-bind="option"
data-bs-combobox-option
data-bs-value="designer"
>Designer</div>
<div
class="bs-combobox-option"
x-bind="option"
data-bs-combobox-option
data-bs-value="engineer"
>Engineer</div>
<div
class="bs-combobox-option"
x-bind="option"
data-bs-combobox-option
data-bs-value="product-manager"
>Product manager</div>
<div class="bs-combobox-empty" data-bs-combobox-empty hidden>
No roles found
</div>
</div>
</div>
</div>
</form>React
JSX · Complete React component
import "@boobstrap/boobstrap";
import { useCombobox } from "@boobstrap/react";
const roles = [
{ value: "designer", label: "Designer" },
{ value: "engineer", label: "Engineer" },
{ value: "product-manager", label: "Product manager" },
{ value: "founder", label: "Founder" },
];
export function TeamRoleSelect() {
const role = useCombobox({ options: roles });
return (
<div className="bs-form-group">
<label className="bs-label" htmlFor="react-role">Team role</label>
<div className="bs-combobox" {...role.getRootProps()}>
<input
className="bs-combobox-input"
id="react-role"
placeholder="Search roles"
{...role.getInputProps()}
/>
<button
className="bs-combobox-toggle"
{...role.getToggleProps({ "aria-label": "Toggle roles" })}
/>
<input type="hidden" name="team_role" value={role.value} readOnly />
<div className="bs-combobox-listbox" {...role.getListboxProps()}>
{role.filteredOptions.map((option, index) => (
<div
className="bs-combobox-option"
key={option.value}
{...role.getOptionProps(option, index)}
>
{option.label}
</div>
))}
{role.filteredOptions.length === 0 && (
<div className="bs-combobox-empty">No roles found</div>
)}
</div>
</div>
</div>
);
}Vue
Vue · Complete searchable select
<script setup>
import "@boobstrap/boobstrap";
import { useCombobox } from "@boobstrap/vue";
const roles = [
{ value: "designer", label: "Designer" },
{ value: "engineer", label: "Engineer" },
{ value: "product-manager", label: "Product manager" },
{ value: "founder", label: "Founder" },
];
const role = useCombobox({ options: roles });
</script>
<template>
<div class="bs-form-group">
<label class="bs-label" for="vue-role">Team role</label>
<div class="bs-combobox" v-bind="role.getRootProps()">
<input class="bs-combobox-input" id="vue-role" placeholder="Search roles"
v-bind="role.getInputProps()" />
<button class="bs-combobox-toggle"
v-bind="role.getToggleProps({ 'aria-label': 'Toggle roles' })"></button>
<input type="hidden" name="team_role" :value="role.value" />
<div class="bs-combobox-listbox" v-bind="role.getListboxProps()">
<div v-for="(option, index) in role.filteredOptions" :key="option.value"
class="bs-combobox-option"
v-bind="role.getOptionProps(option, index)">
{{ option.label }}
</div>
<div v-if="role.filteredOptions.length === 0" class="bs-combobox-empty">
No roles found
</div>
</div>
</div>
</div>
</template>