72 lines
2.3 KiB
Svelte
72 lines
2.3 KiB
Svelte
<script>
|
|
import CommonHelper from "@/utils/CommonHelper";
|
|
import Select from "@/components/base/Select.svelte";
|
|
import BaseSelectOption from "@/components/base/BaseSelectOption.svelte";
|
|
|
|
// original select props
|
|
export let items = []; // for groups support wrap in `[{group: 'My group', items: [...]}]`
|
|
export let multiple = false;
|
|
export let selected = multiple ? [] : undefined;
|
|
export let labelComponent = BaseSelectOption; // custom component to use for each selected option label
|
|
export let optionComponent = BaseSelectOption; // custom component to use for each dropdown option item
|
|
|
|
// custom props
|
|
export let selectionKey = "value";
|
|
export let keyOfSelected = multiple ? [] : undefined;
|
|
|
|
$: if (items) {
|
|
handleKeyOfSelectedChange(keyOfSelected);
|
|
}
|
|
|
|
$: handleSelectedChange(selected);
|
|
|
|
function handleKeyOfSelectedChange(newKeyOfSelected) {
|
|
newKeyOfSelected = CommonHelper.toArray(newKeyOfSelected, true);
|
|
|
|
let newSelected = [];
|
|
let allItems = getFlattenItems();
|
|
|
|
for (let item of allItems) {
|
|
if (CommonHelper.inArray(newKeyOfSelected, item[selectionKey])) {
|
|
newSelected.push(item);
|
|
}
|
|
}
|
|
|
|
if (newKeyOfSelected.length && !newSelected.length) {
|
|
return; // options are still loading...
|
|
}
|
|
|
|
selected = multiple ? newSelected : newSelected[0];
|
|
}
|
|
|
|
async function handleSelectedChange(newSelected) {
|
|
let extractedKeys = CommonHelper.toArray(newSelected, true).map((item) => item[selectionKey]);
|
|
|
|
if (!items.length) {
|
|
return; // options are still loading...
|
|
}
|
|
|
|
keyOfSelected = multiple ? extractedKeys : extractedKeys[0];
|
|
}
|
|
|
|
function getFlattenItems() {
|
|
if (!CommonHelper.isObjectArrayWithKeys(items, ["group", "items"])) {
|
|
return items; // already flatten
|
|
}
|
|
|
|
// extract items from groups
|
|
let result = [];
|
|
for (const group of items) {
|
|
result = result.concat(group.items);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
</script>
|
|
|
|
<Select bind:selected {items} {multiple} {labelComponent} {optionComponent} on:show on:hide {...$$restProps}>
|
|
<svelte:fragment slot="afterOptions">
|
|
<slot name="afterOptions" />
|
|
</svelte:fragment>
|
|
</Select>
|