feat: add focusSelectedItem flag to combo-box#9194
Conversation
| comboBox.addEventListener('vaadin-combo-box-dropdown-opened', resolveFocusSelectedItem); | ||
| // `_onOpened` doesn't re-run on filter change, so the web component can't | ||
| // re-arm its own `__shouldFocusSelectedItem` latch — re-resolve ourselves. | ||
| comboBox.addEventListener('filter-changed', () => { |
There was a problem hiding this comment.
I think I would prefer if it would not do that. If I enter a new filter, I likely want to select a different item. Based on the filtered results I then want to scan the list from top to bottom. Then it doesn't sound helpful that it scrolls down somewhere to the current selection.
cfa1c60 to
81e662d
Compare
81e662d to
c9c2fac
Compare
b953e19 to
d2b850b
Compare
988b0ff to
bcb3096
Compare
Drop comments that explain choices made during the PR rather than non-obvious WHY of the resulting code. Historical context (why the microtask poll, why the connector holds the flag, full close-time reset rationale) moved to PR #9194. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bcb3096 to
8576f92
Compare
|
Reviewer notes — context for the trimmed comments The latest commit (
|
Drop comments that explain choices made during the PR rather than non-obvious WHY of the resulting code. Historical context (why the microtask poll, why the connector holds the flag, full close-time reset rationale) moved to PR #9194. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8576f92 to
ee8cb4c
Compare
Drop comments that explain choices made during the PR rather than non-obvious WHY of the resulting code. Historical context (why the microtask poll, why the connector holds the flag, full close-time reset rationale) moved to PR #9194. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ee8cb4c to
d5c473f
Compare
4e16446 to
dd555eb
Compare
Drop comments that explain choices made during the PR rather than non-obvious WHY of the resulting code. Historical context (why the microtask poll, why the connector holds the flag, full close-time reset rationale) moved to PR #9194. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
d5c473f to
d3d5dfd
Compare
Drop comments that explain choices made during the PR rather than non-obvious WHY of the resulting code. Historical context (why the microtask poll, why the connector holds the flag, full close-time reset rationale) moved to PR #9194. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
d3d5dfd to
d1e5bb3
Compare
Drop comments that explain choices made during the PR rather than non-obvious WHY of the resulting code. Historical context (why the microtask poll, why the connector holds the flag, full close-time reset rationale) moved to PR #9194. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
d1e5bb3 to
90f8fb0
Compare
41130c6 to
ec9814b
Compare
Drop comments that explain choices made during the PR rather than non-obvious WHY of the resulting code. Historical context (why the microtask poll, why the connector holds the flag, full close-time reset rationale) moved to PR #9194. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
90f8fb0 to
e37d071
Compare
Drop comments that explain choices made during the PR rather than non-obvious WHY of the resulting code. Historical context (why the microtask poll, why the connector holds the flag, full close-time reset rationale) moved to PR #9194. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
e37d071 to
b484d19
Compare
Drop comments that explain choices made during the PR rather than non-obvious WHY of the resulting code. Historical context (why the microtask poll, why the connector holds the flag, full close-time reset rationale) moved to PR #9194. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
b484d19 to
720a058
Compare
6e45890 to
7da590b
Compare
Adds `setFocusSelectedItem(boolean)` / `isFocusSelectedItem()` to `ComboBox`. When enabled and a value is set, opening the dropdown scrolls to and focuses the selected item. Index resolution happens server-side via a `@ClientCallable resolveSelectedItemIndex()`: - In-memory data view: `getListDataView().getItemIndex(T)`. - Lazy data view: `getLazyDataView().getItemIndex(T)`, which delegates to the configured `ItemIndexProvider`. - Returns null (silent fallback) when no value, no data provider, no ItemIndexProvider configured for a lazy data provider, or in-memory client-side filter mode (where the server doesn't see the filter). The connector wires `vaadin-combo-box-dropdown-opened` to the resolve flow with three-guard token cancellation (microtask entry, pre-RPC, post-RPC) so stale invocations under rapid filter / open changes drop correctly. The Java setter writes a connector-side flag via `$connector.setFocusSelectedItem(value)` rather than a web-component property, since the closed `vaadin/web-components#11554` PR removed the WC's own `focusSelectedItem` property. An `opened-changed` listener arms `serverFacade.needsDataCommunicatorReset()` on close when `focusSelectedItem && selectedItem` is set, so the next open's `setViewportRange` doesn't no-op against the server's last-sent range and leave the combo stuck loading. Adds `ComboBoxFocusSelectedItemPage` and `ComboBoxFocusSelectedItemIT` covering preset values, lazy / in-memory / Person / Binder paths, default-off, throwing-provider, no-provider, filter interactions, and edge cases (push-update, detach-reattach, replace-items). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When the dropdown closes with `focusSelectedItem` enabled, the existing armed `serverFacade.needsDataCommunicatorReset()` triggers the server's `dataCommunicator.reset()` on the next setViewportRange RPC. That reset interacts with the data communicator's normal passivate-and-unregister flow: items outside the active range post-reset get their `KeyMapper` entries removed and are issued fresh keys when re-fetched. Cached pages in the connector (`cache`, `committedPages`) and in the WC's data-provider controller (`rootCache`) survive the reset on the client side, so they hold items with stale `key` values. After a subsequent `setValue(...)` re-allocates a fresh key for the selected item, selection-highlight comparison via `itemIdPath="key"` no longer matches the cached item — the dropdown shows the selected item but without the "selected" attribute, and the focusSelectedItem RPC's `scrollToIndex(index)` lands on a real (cached) item whose key is already orphaned. Wipe all client-side cache state on close so the next open populates from the post-reset server data with current keys. Reproduces with the three-sequence test: click 123 + open/close, click 9000 + open/close, click 123 + open. Without this fix, the final open shows Item 123 highlighted as focused but not as selected, because filteredItems[123].key still holds the original key from the first sequence while selectedItem.key is the freshly-allocated one. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop comments that explain choices made during the PR rather than non-obvious WHY of the resulting code. Historical context (why the microtask poll, why the connector holds the flag, full close-time reset rationale) moved to PR #9194. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…lter Listens on `opened-changed` instead of `vaadin-combo-box-dropdown-opened` so the auto-focus resolve only fires on real opens — the WC briefly toggles `_overlayOpened` during filter changes when the items list empties and refills, and the previous listener was re-running the resolve mid-filter, parking `__scrollToPendingIndex` on the next fetch and re-scrolling once the data landed. Also adds a `filter-changed` cleanup: resets `_focusedIndex` so the WC's `_setDropdownItems` restoration logic falls through to label-match (returning -1 for an empty filter) instead of carrying the previously- focused item across the filter change, and bumps the resolve token to cancel any in-flight resolve whose late `scrollToIndex` would otherwise land after the filter changed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…r code Tightens the long block above `focusSelectedItemToken`, the per-async-edge narration inside `resolveFocusSelectedItem`, and the listener docstrings. WHY-comments stay (switchMap-style cancellation, the loading-settle rationale, the `opened-changed` vs. `dropdown-opened` choice, the `_setDropdownItems` filter-carry behavior, the close-handler reset chain); WHAT-comments shrink or go. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
376c4ff to
a73e2ed
Compare
|
|
Closing in favor of #9238 |



Summary
Re-enables an opt-in version of the dropdown behavior removed in web-components#6055: when the dropdown opens, the overlay scrolls to and visually focuses the currently-selected item. Useful for long lists where the user wants to see/confirm their selection on open.
Adds
ComboBox.setFocusSelectedItem(boolean)/isFocusSelectedItem()plus an@ClientCallable resolveSelectedItemIndex()that resolves the authoritative index for the current value viaItemIndexProvider(lazy) or the list data view (in-memory). The connector listens for the dropdown-open event and scrolls to the resolved index.Fixes vaadin/web-components#6061.
Depends on
fix(combo-box): preserve committed pages in connector range management. This PR is stacked on top; base will be retargeted tomainonce fix: preserve committed pages in connector range management in combo-box #9220 merges. Without fix: preserve committed pages in connector range management in combo-box #9220, thescrollToIndexto a far/unloaded page leaves the dropdown stuck loading.comboBox.scrollToIndex(index)method the connector calls. Must land in@vaadin/combo-boxbefore this PR can merge.Notes for reviewers
A summary comment with the deeper rationale (token-based cancellation, close-time
KeyMapperre-key handling, microtask polling for the connector flag) is posted as a separate PR comment to keep the diff readable.