Skip to content

FormAutocomplete commits partial input values per keystroke with allowFreeText #32

@d34dman

Description

@d34dman

Summary

FormAutocomplete.svelte:305-318 (handleInput) calls onChange(inputValue) on every keystroke when allowFreeText: true. The search-box text and the field's committed value are conflated, so partial strings typed into the search box land in the parent form's edits buffer and get committed to history on the next blur.

Surfaced while investigating #31 — same root concern (autocomplete's internal UI state leaking into form/history state), different path.

Repro

  1. Configure a FormAutocomplete with allowFreeText: true.
  2. Mount it inside a ConfigForm and select a real option, e.g. option-A.
  3. Click into the autocomplete and type opt-B (or any partial text), then tab out without selecting an option.
  4. Inspect the workflow store / history.
  5. The committed value is the literal string 'opt-B' — a partial, never-selected value — and that's now the top history entry.

Why it's wrong

<select> works fine with onChange-per-change because the value is atomic at every point. Text/number/range work fine because the keystroke is the value. Autocomplete is the outlier: it has an internal inputValue (search query) that is not the field's value. Treating them as one means transient UI state pollutes domain state.

Suggested fix

FormAutocomplete should only emit onChange on commit-worthy events:

  • Option selected (already correct — handleOption)
  • Tag added/removed in multiple mode (already correct)
  • Enter pressed with allowFreeText and non-empty input (already correct)
  • Blur with allowFreeText and non-empty input (currently this commits transitively via the per-keystroke path; should be the only free-text commit path)

Drop the per-keystroke onChange(inputValue) in handleInput (line 314). The component already maintains inputValue as $state for the search UI; it just shouldn't be telling the form about it until the user has signalled intent.

Scope

~10 lines in FormAutocomplete.svelte. Doesn't touch the form layer or the history layer. Independent of #31's structural fix.

Out of scope (separate issue)

The clearing-effect on dependency change (onChange('') when a params field's value flips) has the same architectural problem — child unilaterally mutates parent state. That manifests on undo of a dependency field. Worth its own issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions