Events
DotSelect dispatches custom DOM events on the original <select> element. Listen for them with addEventListener.
Listening for Events
js
const el = document.querySelector('#my-select');
el.addEventListener('ds:change', (e) => {
console.log('New value:', e.detail.value);
});Or with a DotSelect instance:
js
const select = DotSelect.getInstance(el);
select.getElement().addEventListener('ds:change', (e) => {
console.log('New value:', e.detail.value);
});Events Reference
| Event | Description | Fires When |
|---|---|---|
ds:change | Value changed | User selects, deselects, or clears a value |
ds:open | Dropdown opened | Dropdown becomes visible |
ds:close | Dropdown closed | Dropdown is hidden |
ds:search | Search input changed | User types in the search box |
ds:clear | Selection cleared | User clicks the clear button |
ds:loading | Loading state changed | AJAX request starts or finishes |
ds:error | Error occurred | AJAX request fails or a runtime error occurs |
ds:item:add | Item added | An item is selected (single or multiple) |
ds:item:remove | Item removed | An item is deselected (multiple mode) |
ds:populated | Options populated | Options are loaded (from AJAX or static data) |
ds:refreshed | Component refreshed | refresh() method completes |
ds:chain:ready | Chain initialized | All members of a chain group are ready |
ds:chain:change | Chain value changed | Any member in the chain changes value |
Event Detail Payloads
ds:change
js
el.addEventListener('ds:change', (e) => {
e.detail.value; // string | string[] — current value(s)
e.detail.data; // object | object[] — full data for selected option(s)
e.detail.instance; // DotSelect — the instance
});ds:open
js
el.addEventListener('ds:open', (e) => {
e.detail.instance; // DotSelect
});ds:close
js
el.addEventListener('ds:close', (e) => {
e.detail.instance; // DotSelect
});ds:search
js
el.addEventListener('ds:search', (e) => {
e.detail.term; // string — the search query
e.detail.results; // number — count of matching options
e.detail.instance; // DotSelect
});ds:clear
js
el.addEventListener('ds:clear', (e) => {
e.detail.previousValue; // string | string[] — value before clearing
e.detail.instance; // DotSelect
});ds:loading
js
el.addEventListener('ds:loading', (e) => {
e.detail.loading; // boolean — true when loading starts, false when done
e.detail.instance; // DotSelect
});ds:error
js
el.addEventListener('ds:error', (e) => {
e.detail.error; // Error — the error object
e.detail.type; // string — error type: "ajax", "parse", "runtime"
e.detail.instance; // DotSelect
});ds:item:add
js
el.addEventListener('ds:item:add', (e) => {
e.detail.value; // string — the added item's value
e.detail.data; // object — full data for the added item
e.detail.instance; // DotSelect
});ds:item:remove
js
el.addEventListener('ds:item:remove', (e) => {
e.detail.value; // string — the removed item's value
e.detail.data; // object — full data for the removed item
e.detail.instance; // DotSelect
});ds:populated
js
el.addEventListener('ds:populated', (e) => {
e.detail.options; // object[] — array of option data objects
e.detail.source; // string — "ajax", "static", or "cache"
e.detail.instance; // DotSelect
});ds:refreshed
js
el.addEventListener('ds:refreshed', (e) => {
e.detail.instance; // DotSelect
});ds:chain:ready
js
el.addEventListener('ds:chain:ready', (e) => {
e.detail.group; // string — the chain group name
e.detail.members; // DotSelect[] — all instances in the chain
});ds:chain:change
js
el.addEventListener('ds:chain:change', (e) => {
e.detail.group; // string — the chain group name
e.detail.index; // number — the index of the changed member
e.detail.value; // string — the new value
e.detail.values; // object — all current values in the chain
e.detail.instance; // DotSelect — the changed instance
});Usage Examples
Form Validation
js
const el = document.querySelector('#required-select');
el.addEventListener('ds:change', (e) => {
const isValid = e.detail.value !== '' && e.detail.value !== null;
el.closest('.form-group').classList.toggle('is-invalid', !isValid);
});Conditional Logic
Show/hide a text field based on selection:
js
const el = document.querySelector('#category-select');
const otherField = document.querySelector('#other-category');
el.addEventListener('ds:change', (e) => {
otherField.style.display = e.detail.value === 'other' ? 'block' : 'none';
});Logging AJAX Errors
js
document.querySelectorAll('[data-dot-select][data-ajax-url]').forEach((el) => {
el.addEventListener('ds:error', (e) => {
console.error(`DotSelect AJAX error on #${el.id}:`, e.detail.error);
});
});Syncing Multiple Selects
js
const source = document.querySelector('#source-select');
const mirror = DotSelect.getInstance(document.querySelector('#mirror-select'));
source.addEventListener('ds:change', (e) => {
mirror.setValue(e.detail.value);
});Chain Completion Handler
js
const citySelect = document.querySelector('[data-chain-group="location"][data-chained-index="2"]');
citySelect.addEventListener('ds:chain:change', (e) => {
if (e.detail.index === 2 && e.detail.value) {
console.log('Full location selected:', e.detail.values);
// { 0: "us", 1: "ca", 2: "sf" }
}
});TIP
Events bubble up the DOM tree. You can listen on a parent container to handle events from multiple DotSelect instances:
js
document.querySelector('#my-form').addEventListener('ds:change', (e) => {
console.log('A select changed:', e.target.id, e.detail.value);
});