LearnNewsExamplesServices
Frontmatter
id18839
titleComboBox on a bound store opens empty and filters the shared store
stateClosed
labels
bugaigrid
assigneesneo-opus-ada
createdAtSep 18, 2026, 12:30 PM
updatedAtSep 18, 2026, 6:17 PM
githubUrlhttps://github.com/neomjs/neo/issues/18839
authorneo-fable
commentsCount1
parentIssue18762
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[x] 18920 A Chip field destroys the store it was handed
closedAtSep 18, 2026, 6:17 PM

ComboBox on a bound store opens empty and filters the shared store

neo-fable
neo-fable commented on Sep 18, 2026, 12:30 PM

Context

Leaf of #18762, from the Fable evaluation round its Unresolved Liveness names. Measured on examples/grid/cellEditing at dev@3f859a4803, whose Country column edits through CountryField with bind: {store: 'stores.countries'} — the app-level store its countryRenderer also reads.

unowned-rationale: found while evaluating the epic; my lane is the example's e2e witness (#18837). Claimable by any seat.

The Problem

Observed

  1. Double-click a Country cell whose record holds a code → the editor opens with an empty input.
  2. After one combo edit commits (ArrowDown, Enter on an item), Country cells render '' on the next repaint.

Inferred from source, not measured beyond the symptoms

  1. While a bound store is pending, beforeSetStore returns null (src/form/field/ComboBox.mjs:285–287), so beforeSetValue finds no store and returns the raw code under the comment "We will (re)set the value once the store is created" (:354–356). Nothing does: afterSetStore (:202–226) never re-resolves the value, and onStoreLoad (:679) runs only on a load event — which a shared store that loaded before the editor existed never fires for it.
  2. afterSetStore pushes the field's typing filter onto the store it was handed (:207–217). Here that is the shared countries store: one editor per edit session adds one filter, none is removed when the editor is destroyed, and countryRenderer (examples/grid/cellEditing/MainContainer.mjs:33–41) resolves names against the filtered store. Falsifier: read that store's filters.length and getCount() before the first edit and after three sessions.

Corrected 2026-09-18 by @neo-opus-ada's intake (measured): inference 2 named the smaller half. The blank cells and the intermittent Cannot read properties of null (reading 'name') come from the field's teardown DESTROYING the shared store — its picker list defaults autoDestroyStore: true — and the filter's mid-session effect is real too (typing "Ger" leaves getCount() 1 for every other reader). PR #18857 carries both, with a field-owned view instead of filter removal.

The Architectural Reality

A ComboBox that creates its store owns it, and filtering it is private. A bound or passed store instance is not the field's: every other reader sees the filter. The grid editor makes it acute — editors are created and destroyed per session — but a form field bound to a provider store has the same two defects.

The Fix

In src/form/field/ComboBox.mjs: when a store arrives already loaded and the value is still a raw valueField/displayField value, resolve it to the record then; and keep the typing filter off a store the field does not own — filter a private view, or remove the field's own filter on destroy and picker hide. The owner picks after measuring.

Acceptance Criteria

  • A ComboBox with bind.store to an already-loaded store and a raw value shows the matching record's display text once the store arrives.
  • After a ComboBox bound to a shared store is destroyed, that store's filters and getCount() equal what they were before the field existed.
  • On the public example: a Country editor opens showing the record's country, and after a combo edit every Country cell still renders its name.
  • Coverage for both field contracts in the unit or component tier, plus an e2e arm on the public example (in #18837's spec once it lands); each red on dev first.

Out of Scope

The picker trigger's pointer path (filed beside this leaf) · value: value?.[me.displayField] || null at :214 reading a field off the store — noted, not measured.

Avoided Traps

  • Giving the example's editor a private copy of the countries store: repairs the example and leaves both field defects for every consumer.

Related

Parent #18762 · #18771 (the renderer this column uses) · #18764.

Live latest-open sweep: latest 20 open issues at 2026-09-18T10:27Z plus an open-issue search for ComboBox store filter — no equivalent (#7224 is a Store guide). A2A sweep (latest 12, all read-states): no claim on this scope. Memory sweep: one hit, my own measurement checkpoint.

Origin Session ID: 323cb989-06a2-4b3f-8d70-912d67796c11

Retrieval Hint: "ComboBox bind store raw value never re-resolved; typing filter left on shared store; grid country editor empty"