Description
Current Behavior
Hi, I'm using the Combobox component from @skeletonlabs/skeleton-svelte with Svelte 5 . I'm updating the data
prop dynamically based on user input, fetching countries from a local JSON file when the input has 2 or more characters. The countries
array updates correctly (confirmed via console logs and rendering in a <select>
element), but the Combobox doesn't reflect these changes until an additional input event occurs. For example, when typing "co", it shows 8 countries in logs but the Combobox remains empty; when I delete a character (to "c"), it shows the previous 8 countries instead of clearing. Using a native <select>
works perfectly. Is there a known issue with Combobox reactivity in Svelte 5, or am I missing a specific prop/event to make it update dynamically? Here's my code:
<script lang="ts">
import { Combobox } from '@skeletonlabs/skeleton-svelte';
interface ComboboxData {
label: string;
value: string;
emoji: string;
}
interface CountryResponse {
translations: { es: string };
iso3: string;
emoji?: string;
}
const COUNTRIES_DATA: CountryResponse[] = [
{ translations: { es: 'Argentina' }, iso3: 'ARG', emoji: 'π¦π·' },
{ translations: { es: 'Bolivia' }, iso3: 'BOL', emoji: 'π§π΄' },
{ translations: { es: 'Colombia' }, iso3: 'COL', emoji: 'π¨π΄' },
{ translations: { es: 'Costa Rica' }, iso3: 'CRI', emoji: 'π¨π·' },
{ translations: { es: 'Comoras' }, iso3: 'COM', emoji: 'π°π²' },
{ translations: { es: 'Congo' }, iso3: 'COG', emoji: 'π¨π¬' },
{ translations: { es: 'Chile' }, iso3: 'CHL', emoji: 'π¨π±' },
{ translations: { es: 'Ecuador' }, iso3: 'ECU', emoji: 'πͺπ¨' },
{ translations: { es: 'MΓ©xico' }, iso3: 'MEX', emoji: 'π²π½' },
{ translations: { es: 'PerΓΊ' }, iso3: 'PER', emoji: 'π΅πͺ' }
];
let countries: ComboboxData[] = $state([]);
let selectedCountry = $state(['']);
async function searchCountries(input: string): Promise<void> {
try {
console.log(input.length, 'size');
if (input.length >= 2) {
console.log('search');
const filtered = COUNTRIES_DATA.filter(
(country) =>
country.translations?.es &&
country.translations.es.toLowerCase().startsWith(input.toLowerCase())
);
console.log('FILTERED:', filtered);
countries = [
...filtered.map(({ translations, iso3, emoji }) => ({
label: translations.es ?? '',
value: iso3 ?? '',
emoji: emoji || ''
}))
];
console.log('Countries updated:', countries);
} else {
console.log('clear');
countries = [];
}
} catch (e) {
console.error('Error fetching countries:', e);
countries = [];
}
}
</script>
<div style="margin-bottom: 24px;">
<h2
style="border-bottom: 1px solid #ccc; padding-bottom: 8px; font-size: 1.25rem; font-weight: bold; color: #333; display: flex; align-items: center; gap: 8px;"
>
Location
</h2>
<div style="display: grid; grid-template-columns: 1fr; gap: 24px; max-width: 800px;">
<div style="margin-bottom: 16px;">
<label
style="display: flex; align-items: center; gap: 8px; font-size: 0.95rem; font-weight: 500; color: #444;"
for="country"
>
Country
</label>
<Combobox
data={countries}
value={selectedCountry}
onValueChange={(e) => (selectedCountry = e.value)}
onInputValueChange={(e) => searchCountries(e.inputValue)}
label=""
placeholder="Select..."
>
{#snippet item(item)}
<div style="display: flex; justify-content: space-between; width: 100%; gap: 8px;">
<span>{item.label}</span>
<span>{item.emoji}</span>
</div>
{/snippet}
</Combobox>
<select bind:value={selectedCountry} style="width: 100%; padding: 6px; margin-top: 8px;">
{#each countries as country}
<option value={country.value}>{country.label} {country.emoji}</option>
{/each}
</select>
</div>
</div>
</div>
Expected Behavior
- The Combobox should dynamically update its dropdown to reflect changes in the
data
prop immediately. - Typing 2+ characters (e.g., "co") should display filtered countries (e.g., "Colombia", "Costa Rica").
- Deleting to <2 characters (e.g., "c") should clear the dropdown.
- The behavior should match a native
<select>
, which renders the same data correctly.
Steps To Reproduce
- Set up a Svelte 5 project with
@skeletonlabs/skeleton-svelte
. - Copy and paste the code attached.
- Type "co" in the Combobox input.
- Observe that the Combobox does not display the filtered countries, despite the data updating correctly (verified via console logs and a native
<select>
). - Delete to "c" and observe that the Combobox shows the previously filtered countries instead of an empty dropdown.
Link to Reproduction / Stackblitz
No response
Environment Information
System:
OS: Linux 6.11 Linux Mint 22.1 (Xia)
CPU: (16) x64 AMD Ryzen 7 7730U with Radeon Graphics
Memory: 8.13 GB / 15.03 GB
Container: Yes
Shell: 5.2.21 - /bin/bash
Binaries:
Node: 22.13.0 - ~/.volta/tools/image/node/22.13.0/bin/node
npm: 10.9.2 - ~/.volta/tools/image/node/22.13.0/bin/npm
pnpm: 9.15.4 - ~/.volta/bin/pnpm
Browsers:
Brave Browser: 138.1.80.115
Chrome: 138.0.7204.92
npmPackages:
@skeletonlabs/skeleton: ^3.1.4 => 3.1.4
@skeletonlabs/skeleton-svelte: ^1.2.4 => 1.2.4
More Information
I noticed that when I type βCoβ and the comboBox doesn't show anything if I remove the focus and put it back on the input it loads correctly, seems like a synchronization problem?