Fix pre-filled value reset when clicking outside - #285
Conversation
Currently, it always returns `undefined` (falsy)
josefarias
left a comment
There was a problem hiding this comment.
Thanks @Spone, I'm having a hard time reasoning through how this could happen organically so I used Claude to try and reproduce and it, too, had a hard time. Here's what it had to say (edited slightly by me, I think its reasoning is sound):
Thanks for tracking this down! A couple of things:
1. Is this still reproducible on the latest
main? I couldn't trigger the prefilled reset organically, and I think the diagnosis may predate some code that's now on main. The root cause says_runCallbackcalls_selectOnQuerywithhw:lockInSelection— but the controller now guards that (} else if (inputType !== "hw:lockInSelection")), so that branch is unreachable; the real lock-in goes through_lockInSelection→_ensurableOption. Also, on a plain open our async combobox runs_preselectSingle(the lazy-frame load has nocallback_id), so the option is marked and_ensurableOptionnever reaches the new fallback. Since_preselectSingleand the fix use the identical_optionElementWithValue(fieldValue)lookup, the fallback only matters if a re-render dropsaria-selectedafter preselect (a Turbo stream re-rendering the listbox). Could you confirm it still reproduces on currentmain, and share the combobox config + what re-renders the listbox between open and click-away? A minimal repro would let us add a real regression test.2. Regardless, this regresses
include_blank. The new_optionElementWithValue(this._fieldValue)matches the blank option (data-value="") when the value is empty. Repro: blank combobox → type a non-matching query → click away → display resets to the blank label instead of staying empty. Passes onmain, fails here. Guard:get _ensurableOption() { return this._selectedOptionElement || this._optionElementWithFieldValue || this._visibleOptionElements[0] } get _optionElementWithFieldValue() { if (this._hasFieldValue) return this._optionElementWithValue(this._fieldValue) }
Don't bother replying to everything it's asking. What I’d ask, if possible, is if you could provide a minimal reproduction repo (or a failing test case). Something I can run myself and see the behavior because I haven't been able to replicate just yet (reliably or not).
Separately, I do think the bug Claude points out is legit.
Problem
When an async combobox has a pre-filled value and the user opens it then clicks away without changing anything, the selection resets to the first alphabetical option instead of preserving the current value.
Kapture.2026-02-21.at.22.25.27.mp4
Root cause
For async comboboxes, opening triggers a fetch whose response arrives via Turbo Stream. At that point,
_runCallbackis called (not_preselectSingle), which calls_selectOnQuerywithinputType = "hw:lockInSelection". This hits the branch:Since no option has
aria-selected=trueyet (_preselectSinglewas bypassed),_selectedOptionElementis null, so_ensurableOptionfalls back to_visibleOptionElements[0]— the first alphabetical option — which gets incorrectly selected.Fixes
Fix 1 —
_hasSelection: adds missingreturnstatements so the getter correctly reports whether a value is selected. Fixes the issue for sync comboboxes.Fix 2 —
_ensurableOption: adds_optionElementWithValue(this._fieldValue)as an intermediate fallback, so when no option is marked selected but the hidden field has a value, the matching option is found and preserved instead of falling back to the first visible one. Fixes the issue for async comboboxes.After the fix
Kapture.2026-02-21.at.22.28.07.mp4