Standard
Base, simple version.
Base version without search.
When you need a richer select without going overboard, Selectamelo adds search, multi, and clear while staying small and dependency-free. It keeps the native select in the DOM so forms keep working, and it remains keyboard-first by default.
No jQuery, no framework, just a light upgrade to the native control. You get disabled and readonly states, clean events, and a UI that stays fast even on short lists.
Base, simple version.
Base version without search.
Filter fast and handle empty states.
Use ↑ ↓ and Enter to select.
Chips with inline removal.
Backspace removes the last chip.
Selectamelo mirrors native select semantics: disabled, readonly, and live change updates. Here are two common cases.
Choose the global build or the package.
npm install selectamelo
import { Selectamelo } from "selectamelo";
<link rel="stylesheet" href="./styles.css" />
<script src="./selectamelo.global.js"></script>
The global build exposes Selectamelo on window.
A native select, no custom markup.
<select id="team" data-selectamelo>
<option value=""></option>
<option value="design">Design</option>
<option value="dev">Dev</option>
</select>
Visible placeholder: add an <option value=""></option> at the top.
Call create and keep the instance.
const select = document.getElementById("team");
const inst = Selectamelo.create(select, {
placeholder: "Choose a team",
allowClear: true,
});
If the select is already initialized, create returns the same instance.
Parameters passed to create.
| Option | Type | Default | Notes |
|---|---|---|---|
searchable |
boolean | true | Enable search. |
placeholder |
string | "" | Text shown when nothing is selected. |
allowClear |
boolean | true | Show the X to clear the value. |
hideSearch |
boolean | false | Hide the search input. |
disabled |
boolean | false | Disable the select and do not submit the value. |
readonly |
boolean | false | Lock the UI but still submit the value. |
i18n |
object | - | UI and accessibility strings. |
disabled and readonly can also be changed via API.
Configuration directly in HTML.
| Attribute | Type | Notes |
|---|---|---|
data-selectamelo |
flag | Selector used for batch initialization. |
data-allow-clear |
boolean | Show or hide the X. |
data-hide-search |
boolean | Hide the search box. |
data-searchable |
boolean | Enable or disable search. |
data-disabled |
boolean | Disable the native select. |
data-readonly |
boolean | Lock the UI without disabling submission. |
data-selectamelo-placeholder |
string | Main placeholder. |
data-selectamelo-search-placeholder |
string | Search box placeholder. |
data-selectamelo-clear-title |
string | X tooltip. |
data-selectamelo-clear-aria-label |
string | X aria-label. |
data-selectamelo-remove-chip-aria-label |
string | Aria-label for removing a chip. |
data-selectamelo-no-results |
string | Text when there are no results. |
Booleans: "", true, 1 = true; false, 0 = false.
UI and accessibility strings.
const inst = Selectamelo.create(select, {
i18n: {
placeholder: "Select...",
searchPlaceholder: "Search...",
clearTitle: "Clear",
clearAriaLabel: "Clear selection",
removeChipAriaLabel: "Remove",
noResults: "No results",
},
});
| Key | Notes |
|---|---|
placeholder |
Default text in the control. |
searchPlaceholder |
Search input placeholder. |
clearTitle |
X title for tooltip. |
clearAriaLabel |
X aria-label. |
removeChipAriaLabel |
Aria-label for chip removal. |
noResults |
Message when the list is empty. |
Methods available on Selectamelo.
const inst = Selectamelo.create(select);
const same = Selectamelo.get(select);
Selectamelo.destroy(select);
destroy restores the original select and removes the wrapper.
Full control via JS.
| Method | Signature | Notes |
|---|---|---|
open |
() |
Open the dropdown. |
close |
() |
Close the dropdown. |
setValue |
(value | value[] | null) |
Set the selected value. |
getValue |
() |
Returns string or array. |
clearOptions |
(keepPlaceholder?) |
Remove all options. |
setOptions |
(options, keepPlaceholder?) |
Replace the options list. |
addOption |
(option, selectIt?) |
Add a new option. |
removeOption |
(value) |
Remove an option. |
updateOption |
(value, patch) |
Update label or disabled. |
upsertOption |
(option, selectIt?) |
Create or update an option. |
refresh |
() |
Recompute label and clear state. |
setLoading |
(isLoading) |
Temporarily lock the UI. |
setDisabled |
(isDisabled) |
Disable the native select. |
setReadonly |
(isReadonly) |
Lock the UI without disabling. |
isDisabled |
() |
Disabled state. |
isReadonly |
() |
Readonly state. |
destroy |
() |
Remove the component and restore the select. |
Hooks to integrate external logic.
| Event | Detail | When |
|---|---|---|
zselect:change |
{ value } |
When the value changes. |
zselect:open |
- | When the dropdown opens. |
zselect:close |
- | When the dropdown closes. |
zselect:search |
{ q } |
When the search filter changes. |
zselect:clear |
- | When the user clears the value. |
select.addEventListener("zselect:change", e => {
console.log("Value:", e.detail.value);
});
Full keyboard navigation.
| Key | Action |
|---|---|
ArrowDown |
Open and move to the next option. |
ArrowUp |
Open and move to the previous option. |
Enter |
Select the active option. |
Escape |
Close the dropdown. |
Tab |
Close and move focus to the next element. |
Backspace |
In multi, remove the last chip. |
Enable with multiple on the select.
<select id="channels" data-selectamelo multiple>
<option value=""></option>
<option value="email">Email</option>
<option value="sms">SMS</option>
</select>
Backspace removes the last selected chip.
Disable search for short lists.
<select data-selectamelo data-searchable="false"></select>
Selectamelo.create(select, {
searchable: false,
hideSearch: true,
});
Load options from an API and manage loading.
inst.setLoading(true);
fetch("/api/options")
.then(r => r.json())
.then(items => {
inst.setOptions(items, true);
})
.finally(() => inst.setLoading(false));
Dynamic management: setOptions, loading state, and value updates.