Various examples
This page gives you some examples what can be done and how.
Multiselect
Example how multiselect can be implemented.
<script>
const svg_checked = `<svg>...</svg>`;
const svg_empty = `<svg>...</svg>`;
function svgRenderer(opt, isSelected, _input) {
return `<div class="inlined">${opt.$selected ? svg_checked : svg_empty}<span>${opt.text}</span></div>`;
}
</script>
<Svelecte
multiple
renderer={svgRenderer}
collapseSelection="always"
clearable
keepSelectionInList={true}
searchProps={{skipSort: true}}
></Svelecte><script>
const svg_checked = `<svg>...</svg>`;
const svg_empty = `<svg>...</svg>`;
function svgRenderer(opt, isSelected, _input) {
return `<div class="inlined">${opt.$selected ? svg_checked : svg_empty}<span>${opt.text}</span></div>`;
}
</script>
<Svelecte
multiple
renderer={svgRenderer}
collapseSelection="always"
clearable
keepSelectionInList={true}
searchProps={{skipSort: true}}
></Svelecte>Custom option snippet
Simple example of using snippet instead of render function for dropdown item rendering. Default snippet implementation correctly handles highlighted search. Custom snippet has no ability to do that.
If you need to keep highlighting feature use render function for custom option rendering.
<script>
import Svelecte from 'svelecte'
let options = [
{id: '1', text: 'option X'},
{id: '2', text: 'option Y'},
{id: '3', text: 'option Z'}
];
</script>
{#snippet option(item)}
<div>
{item.$selected ? 'π' : 'π'} {item.text} {item.$selected ? 'β
' : 'βοΈ'}
</div>
{/snippet}
<Svelecte {options} closeAfterSelect={false} value={'1'} {option} /><script>
import Svelecte from 'svelecte'
let options = [
{id: '1', text: 'option X'},
{id: '2', text: 'option Y'},
{id: '3', text: 'option Z'}
];
</script>
{#snippet option(item)}
<div>
{item.$selected ? 'π' : 'π'} {item.text} {item.$selected ? 'β
' : 'βοΈ'}
</div>
{/snippet}
<Svelecte {options} closeAfterSelect={false} value={'1'} {option} />π‘ Replicate "search highlighting" with custom option
<script>
import Svelecte from 'svelecte'
import { highlightSearch } from 'svelecte';
let options = [
{id: '1', text: 'option X'},
{id: '2', text: 'option Y'},
{id: '3', text: 'option Z'}
];
</script>
{#snippet optionWithSearch(item, inputValue)}
<div>
<b>Item:</b> {@html highlightSearch(item, false, inputValue, opt => opt.text)} {item.$selected ? 'π₯' : ''}
</div>
{/snippet}
<Svelecte options={render_options} closeAfterSelect={false} value={'1'} /><script>
import Svelecte from 'svelecte'
import { highlightSearch } from 'svelecte';
let options = [
{id: '1', text: 'option X'},
{id: '2', text: 'option Y'},
{id: '3', text: 'option Z'}
];
</script>
{#snippet optionWithSearch(item, inputValue)}
<div>
<b>Item:</b> {@html highlightSearch(item, false, inputValue, opt => opt.text)} {item.$selected ? 'π₯' : ''}
</div>
{/snippet}
<Svelecte options={render_options} closeAfterSelect={false} value={'1'} />Dependent selects
This functionality is not strictly related to remote fetch, but itβs typical how itβs used. Just set parentValue and
youβre done. If you require parentValue in your fetch URL, just use [parent] placeholder.
<script>
import Svelecte from 'svelecte';
let parentValue = $state(null);
let value = $state();
// ...
</script>
<Svelecte {options} bind:value={parentValue} clearable />
<Svelecte {parentValue} bind:value fetch="/api/[parent]?search=[query]" /><script>
import Svelecte from 'svelecte';
let parentValue = $state(null);
let value = $state();
// ...
</script>
<Svelecte {options} bind:value={parentValue} clearable />
<Svelecte {parentValue} bind:value fetch="/api/[parent]?search=[query]" />Drag & Drop
You can add support for drag & drop reordering by adding svelte-dnd-action library
Reorder selection by dragging: red,blue,purple
<script>
import Svelecte from 'svelecte';
import { dndzone, overrideItemIdKeyNameBeforeInitialisingDndZones, setDebugMode } from 'svelte-dnd-action';
/** my example has no 'id' property */
overrideItemIdKeyNameBeforeInitialisingDndZones('value');
// rest of code ...
</script>
<Svelecte {options} bind:value={value} multiple {dndzone} placeholder="Re-order selected items by dragging" /><script>
import Svelecte from 'svelecte';
import { dndzone, overrideItemIdKeyNameBeforeInitialisingDndZones, setDebugMode } from 'svelte-dnd-action';
/** my example has no 'id' property */
overrideItemIdKeyNameBeforeInitialisingDndZones('value');
// rest of code ...
</script>
<Svelecte {options} bind:value={value} multiple {dndzone} placeholder="Re-order selected items by dragging" />Custom dropdown positioning
When Svelecte is placed inside container with overflow: hidden, dropdown gets clipped. You can fix that by providing positionResolver property. Itβs a svelte action which receives dropdown element,
so you can move it to document.body and position it manually.
positionResolver) positionResolver) <script>
import Svelecte from 'svelecte';
function bodyPositionResolver(node) {
const svelecteEl = node.parentElement;
document.body.appendChild(node);
function reposition() {
const rect = svelecteEl.getBoundingClientRect();
Object.assign(node.style, {
top: `${rect.bottom + window.scrollY}px`,
left: `${rect.left + window.scrollX}px`,
minWidth: `${rect.width}px`
});
}
reposition();
// re-calculate position every time dropdown gets opened
const observer = new MutationObserver(() => node.classList.contains('is-open') && reposition());
observer.observe(node, { attributes: true, attributeFilter: ['class'] });
return {
destroy() {
observer.disconnect();
node.remove();
}
}
}
</script>
<div class="in-overflow">
<Svelecte {options} positionResolver={bodyPositionResolver} />
</div>
<style>
.in-overflow {
position: relative;
overflow: hidden;
}
</style><script>
import Svelecte from 'svelecte';
function bodyPositionResolver(node) {
const svelecteEl = node.parentElement;
document.body.appendChild(node);
function reposition() {
const rect = svelecteEl.getBoundingClientRect();
Object.assign(node.style, {
top: `${rect.bottom + window.scrollY}px`,
left: `${rect.left + window.scrollX}px`,
minWidth: `${rect.width}px`
});
}
reposition();
// re-calculate position every time dropdown gets opened
const observer = new MutationObserver(() => node.classList.contains('is-open') && reposition());
observer.observe(node, { attributes: true, attributeFilter: ['class'] });
return {
destroy() {
observer.disconnect();
node.remove();
}
}
}
</script>
<div class="in-overflow">
<Svelecte {options} positionResolver={bodyPositionResolver} />
</div>
<style>
.in-overflow {
position: relative;
overflow: hidden;
}
</style>