Skip to content

Make the form pickers keep typed text, start with large types and survive a lost circuit #2639

Closed

Description

@pournasserian

Part of #2426 (F-FRM). Follow-up to #2622: findings from an independent review of the merged form pickers. Visibility holds: deleted entries and other sites are filtered out, and _blazor requires a signed-in person. ArrowDown hand-off works.

Findings

  1. High: typing loses characters. The search box renders value="@_text" and re-renders on every oninput, so each render overwrites what was typed since. On localhost, typing with no delay mangled 4 of 4 rounds, and FormPickerTests failed once with no matches.
  2. High: the circuit never starts for a larger type or library. Every option is a parameter of the island and travels in the circuit's start message. Past about 300 entries the message exceeds SignalR's 32 KB limit, the connection closes, and the picker never appears.
  3. High: a lost circuit reloads the form and discards what was typed. When a circuit can't be resumed, the page reloads. A form with a picker loses its title and rationale; a form without one keeps them. This contradicts "a lost circuit costs only the search".
  4. High: on PostgreSQL, overlapping searches share one DbContext. Blazor doesn't serialize async event handlers. Two overlapping lookups throw "A second operation was started on this context instance", which ends the circuit and leads to finding 3. Results can also arrive out of order.
  5. Medium: axe fails on a form with a picker. aria-controls names a list that isn't rendered. Fixed in Keep the entry form's base version and the values a person didn't touch #2638.
  6. Medium: Enter in the search box submits the whole form, saving the earlier choice.
  7. Medium: each keystroke runs a search and a read per hit, with no debounce. The media picker reads the whole library on every keystroke. This widens the windows in findings 1 and 4.
  8. Low: focus drops to the page after choosing and after Escape in the list. The browser test moves focus with FocusAsync, so it doesn't prove keyboard-only use.
  9. Low: the stored choice is labelled "{id} (version N)", not by name, state and id. The label of a hit is the first string in the stored JSON, which can be a date, an enum value or a SKU.
  10. Low: a choice made in the select before the circuit attaches is lost when the island takes over.

Scope

  • The search box owns its text. The server never writes it back while the person types.
  • The island's parameters are the field, the chosen id and its label. The prerendered select loads its own options, at most 200 plus the chosen one.
  • A lost circuit doesn't reload a page that holds a form. The picker says search is unavailable, and the chosen id still posts.
  • Each search reads through a scope of its own, waits for a short pause in typing, and only the newest search's results are shown.
  • Enter in the search box never submits the form. It chooses the single match, or moves to the list.
  • Focus returns to the search box after a choice, Escape or Clear.
  • A choice shows the entry's name, state and short id. The name comes from the type's first text field, in definition order.
  • A value chosen in the select before the circuit attaches is kept. Moved to Keep a picker choice made before the circuit attaches #2654.
  • Tests:
    • A browser test types with no delay and gets the full text.
    • A form whose target type has 500 entries gets its picker.
    • The page keeps typed input when the circuit is lost.
    • Overlapping searches on PostgreSQL.
    • Enter doesn't submit.
    • A keyboard-only path that never calls FocusAsync.
    • Axe on a form with pickers.

Acceptance

  • The picker works with 500 entries in the target type, and typing at full speed keeps every character.
  • A lost circuit never discards a form's input.
  • Searches on PostgreSQL never end the circuit.

Activity

  1. added a commit that references this issue on Oct 20, 2026
    a245fa2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    type:bugDefectv2FluentCMS v2 (v2 branch)

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions