Skip to content

Commit 1f50366

Browse files
author
Ibrahim Haizel
committed
fix: restore grouped options structure without reinitialization to preserve focus
- Add restoreGroupedChoicesWithoutReinit() helper that rebuilds grouped dropdown using Choices grouped payload - Replace empty query handling to use helper instead of flattening choices - Preserves focus and user experience when clearing search queries - Maintains real optgroup headings for grouped options - Fixes Example 3 grouped options behavior without breaking other examples
1 parent 10085b2 commit 1f50366

File tree

1 file changed

+73
-5
lines changed

1 file changed

+73
-5
lines changed

src/lib/components/ui/MultiSelectSearchAutocomplete.svelte

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,57 @@
839839
}
840840
}
841841
842+
// Restore grouped dropdown (with real group headings) without reinitializing Choices
843+
function restoreGroupedChoicesWithoutReinit(selectedValues: string[]) {
844+
if (!choicesInstance || !choicesInstance.initialised) {
845+
console.log(
846+
"⚠️ Choices instance not ready, skipping restoreGroupedChoicesWithoutReinit",
847+
);
848+
return;
849+
}
850+
if (!groups || groups.length === 0) {
851+
console.log(
852+
"ℹ️ No groups available; restoreGroupedChoicesWithoutReinit skipped",
853+
);
854+
return;
855+
}
856+
857+
console.log("📋 Restoring grouped options via grouped payload (no reinit)");
858+
859+
// Clear current list but keep the instance intact (preserves focus)
860+
choicesInstance.clearChoices();
861+
862+
// Build grouped payload excluding currently selected values
863+
const groupedPayload = groups.map((grp: any) => ({
864+
label: grp.label,
865+
disabled: !!grp.disabled,
866+
choices: grp.choices
867+
.filter((ch: any) => !selectedValues.includes(String(ch.value)))
868+
.map((ch: any) => ({
869+
value: String(ch.value),
870+
label: String(ch.text),
871+
disabled: !!(grp.disabled || ch.disabled),
872+
})),
873+
}));
874+
875+
// Compose final list. Single-select keeps placeholder as first item.
876+
const list: any[] = [];
877+
if (!multiple) {
878+
list.push({
879+
value: "",
880+
label: computedPlaceholderText,
881+
placeholder: true,
882+
disabled: false,
883+
selected: false,
884+
});
885+
}
886+
list.push(...groupedPayload);
887+
888+
// Pass grouped data to Choices so it renders headings properly
889+
choicesInstance.setChoices(list, "value", "label", true);
890+
console.log("✅ Grouped options restored in-place");
891+
}
892+
842893
// Initialize Choices.js
843894
onMount(async () => {
844895
console.log("🔧 MultiSelectSearchAutocomplete: onMount started", {
@@ -1536,12 +1587,29 @@
15361587
// newMode === "options": Choices handles filtering automatically
15371588
console.log("📋 Using static choices mode for search");
15381589
1539-
// For empty queries, restore the full grouped structure
1590+
// For empty queries, restore the full grouped structure (with real headings) without reinit
15401591
if (q === "" && groups && groups.length > 0) {
1541-
console.log(
1542-
"🔄 Empty query with grouped options - restoring full structure",
1543-
);
1544-
resetToStaticChoices();
1592+
// Get selected values so we can exclude them from the dropdown
1593+
let selectedValues: string[] = [];
1594+
try {
1595+
const currentValue = choicesInstance.getValue(true);
1596+
if (Array.isArray(currentValue)) {
1597+
selectedValues = currentValue.map((item: any) =>
1598+
String(item.value || item),
1599+
);
1600+
} else if (currentValue && typeof currentValue === "object") {
1601+
selectedValues = [
1602+
String(currentValue.value || currentValue),
1603+
];
1604+
} else if (currentValue) {
1605+
selectedValues = [String(currentValue)];
1606+
}
1607+
} catch (error) {
1608+
console.warn("⚠️ Error getting current value:", error);
1609+
selectedValues = [];
1610+
}
1611+
1612+
restoreGroupedChoicesWithoutReinit(selectedValues);
15451613
return;
15461614
}
15471615

0 commit comments

Comments
 (0)