Repository navigation
Closed
Labels
Milestone
Description
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
- High: typing loses characters. The search box renders
value="@_text"and re-renders on everyoninput, so each render overwrites what was typed since. On localhost, typing with no delay mangled 4 of 4 rounds, andFormPickerTestsfailed once with no matches. - 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.
- 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".
- 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. - Medium: axe fails on a form with a picker.
aria-controlsnames a list that isn't rendered. Fixed in Keep the entry form's base version and the values a person didn't touch #2638. - Medium: Enter in the search box submits the whole form, saving the earlier choice.
- 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.
- 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. - 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.
- 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
Run the header counts in their own scope so signed-in pages load on P…
Make the form pickers keep typed text, start with large types and sur…