Skip to content

Combobox Input Value Not Updating When Value Changes Programmatically #1317

Closed
@tsegreto

Description

@tsegreto

Describe the bug

Description

When programmatically changing the value of a Combobox component created following the docs at https://next.bits-ui.com/docs/components/combobox, the dropdown selection updates correctly, but the input field text doesn't reflect the change.

Steps to Reproduce

Create a reusable Combobox component following the documentation:

<script lang="ts">
	import { Combobox, type WithoutChildrenOrChild, mergeProps } from "bits-ui";
	import { Icon, ChevronUpDown } from "svelte-hero-icons";
	type Item = { value: string; label: string };
	type Props = Combobox.RootProps & {
		items: Item[];
		inputProps?: WithoutChildrenOrChild<Combobox.InputProps>;
		contentProps?: WithoutChildrenOrChild<Combobox.ContentProps>;
	};
	let {
		items,
		value = $bindable(),
		open = $bindable(false),
		inputProps,
		contentProps,
		...restProps
	}: Props = $props();
	let searchValue = $state("");
	const filteredItems = $derived.by(() => {
		if (searchValue === "") return items;
		return items.filter((item) => item.label.toLowerCase().includes(searchValue.toLowerCase()));
	});
	function handleInput(e: Event & { currentTarget: HTMLInputElement }) {
		searchValue = e.currentTarget.value;
	}
	function handleOpenChange(newOpen: boolean) {
		if (!newOpen) searchValue = "";
	}
	const mergedRootProps = $derived(mergeProps(restProps, { onOpenChange: handleOpenChange }));
	const mergedInputProps = $derived(mergeProps(inputProps, { oninput: handleInput }));
</script>
<Combobox.Root bind:value bind:open {...mergedRootProps} type="single">
	<div class="relative">
		<Combobox.Input
			{...mergedInputProps}
			class="border-input bg-background placeholder:text-muted-foreground flex h-10 w-full rounded-md border px-3 py-2 text-base file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm"
		/>
		<Combobox.Trigger class="absolute end-3 top-1/2 size-6 -translate-y-1/2"><Icon src={ChevronUpDown} class="w-5 h-5 text-neutral-600" /></Combobox.Trigger>
	</div>
	<Combobox.Portal>
		<Combobox.Content {...contentProps} class="z-50  bg-white w-[var(--bits-combobox-anchor-width)] min-w-[var(--bits-combobox-anchor-width)]  rounded-md border shadow-md outline-none mt-2 p-1">
			{#each filteredItems as item, i (item.value)}
				<Combobox.Item value={item.value} label={item.label} class="relative flex w-full select-none items-center rounded-sm p-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 cursor-pointer">
					{#snippet children({ selected })}
						<div class="flex flex-col w-full">
							<span class={selected ? "font-medium text-red-500" : ""}>{item.label}</span>
						</div>
					{/snippet}
				</Combobox.Item>
			{:else}
				<span> No results found </span>
			{/each}
		</Combobox.Content>
	</Combobox.Portal>
</Combobox.Root>

Use this component in another file with programmatic value changes:

let myValue = $state("");
const testItems = [
	{ value: "mango", label: "Mango" },
	{ value: "watermelon", label: "Watermelon" },
	{ value: "apple", label: "Apple" },
];
<button onclick={() => (myValue = "apple")}> Select Apple </button>
<Combobox items={testItems} bind:value={myValue} />

Click the "Select Apple" button

Expected Behavior

When clicking the "Select Apple" button (setting myValue = "apple" programmatically), both the dropdown selection AND the input field text should update to display "Apple".

Actual Behavior

The dropdown correctly shows "Apple" as selected, but the input field remains empty or unchanged.

Reproduction

https://stackblitz.com/edit/github-cfbnbfta-fwh7ndgr?file=src%2Froutes%2F%2Bpage.svelte

Logs

System Info

"bits-ui": "1.3.13",
"svelte": "^5.0.0",

Severity

annoyance

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions