slim-select
slim-select copied to clipboard
Feature request: fire event on new item being added to DOM via addable
Use case
I am displaying a long list of ordered options, allowing users to add their own values via the addable
event. After a new item is added I would like to re-order the options in the dropdown.
Current workaround
I am currently storing the original state, and then on every afterChange
event comparing the new values with the original values and re-creating the slim select instance.
This not only results in a flash of no content while re-creating slim select, but also a lot of boilerplate.
const selects = document.querySelectorAll('[data-slim-select]');
selects.forEach(select => {
let slimSelect;
const bindSelect = () => {
if (slimSelect) {
slimSelect.destroy();
}
const options = select.options;
const originalValues = Array.from(options).map(x => x.innerText);
slimSelect = new SlimSelect({
select: select,
events: {
addable: value => value,
afterChange: (newValue) => {
const newValues = newValue.filter(x => !originalValues.includes(x.text));
if (newValues.length === 0) {
return;
}
Array.from(options)
.sort((a, b) => a.innerText.localeCompare(b.innerText))
.forEach(node => select.appendChild(node));
bindSelect();
}
},
settings: {}
});
};
bindSelect();
});
Suggested solution
- Add an
added
event that fires after the DOM has been updated - (nice to have) Add a
rebuild
method (or observe DOM mutations) that rebuilds the slim select list from the DOM
const selects = document.querySelectorAll('[data-slim-select]');
selects.forEach(select => {
const slimSelect = new SlimSelect({
select: select,
events: {
addable: value => value,
/*** NEW 'ADDED' EVENT ***/
added: (newValue) => {
// re-order the DOM elements
Array.from(options)
.sort((a, b) => a.innerText.localeCompare(b.innerText))
.forEach(node => select.appendChild(node));
/*** NEW 'REBUILD' METHOD ***/
slimSelect.rebuild();
}
},
settings: {}
});
});