ReviewOS

stacks/stx

feat(native): make shared Form submission, values, and validation portable

#2088
Closed glennmichael123 opened this 8 days ago ·
8 days ago

Problem

The shared Form component initializes in a native bundle but its submit behavior requires DOM APIs.

Audited at v0.2.546, commit 0013ce66e3.

Reproduced evidence

A screen containing shared Form with an input and submit button compiles and registers onSubmitEditing. Dispatching that registered event through the native bridge rejects with:

TypeError: event.preventDefault is not a function

The next operation in the handler constructs new FormData(event.target), another browser-specific dependency. Merely adding preventDefault would not complete the form contract.

Source: Form submit and field handling.

Requested change

Provide a portable form-value/submission contract so the same Form component works with browser and native controls. Keep validation and form state in shared logic, with platform collection/event behavior behind an adapter.

Acceptance

  • Native field edits update named form values.
  • Submit gathers current values, including initial and hidden values where applicable.
  • Required, custom, change, and blur validation retain shared semantics.
  • Submission state, error/success events, and reset behavior work on both targets.
  • A submit button actually triggers form submission on native; a manually injected event alone is not sufficient coverage.
  • No dependency on DOM FormData or DOM event methods in the shared native execution path.
  • Tests cover an actual shared Form with shared controls, on both targets.

Priority

Third in the portability audit sequence, after portable component props/events and correct control translation. The submit exception was reproduced in a DOM-free bundle harness; subsequent FormData incompatibility is established by source inspection.

8 days ago

Implemented on main through 5d6070f (11 focused commits).

Version: post-v0.2.582 main. These fixes are not yet in a new numbered release; the green publish-commit job is not a patch release.

The actual shared Form now works with shared TextInput, Button, and Checkbox on both browser and DOM-free native targets: named values and hidden/initial values, required/custom/change/blur validation, real submit-button presses, success/error events and helper arguments, submitting state, and cancelable reset with visible-control/model synchronization. Native FormData collection is local and does not require a files capability; multipart upload still does.

Regression coverage: packages/stx/test/native/shared-form.test.ts, form-data.test.ts, form-host.test.ts; packages/stx/test/components/shared-form-browser.test.ts; packages/stx/test/signals/form-reset-browser.test.ts and conditional-component-props.test.ts. The broader local portability run passed 4,021 tests; subsequent focused scope/checkbox checks passed. Fresh CI on the final pushed SHA passed typecheck, lint, test (including build and installed-consumer smoke), and publish-commit: https://github.com/stacksjs/stx/actions/runs/39271824789

Scope limits are documented in docs/guide/native.md: nested successful controls, no external form=id association, disabled-fieldset semantics, file-input collection, or implicit Enter submission. Native radio remains explicitly unsupported. This issue is verified by same-source interaction tests, not a claim of simulator/pixel certification.

8 days ago

Version update: the v0.2.583 tag has now been created at b10f003, which contains the verified forms fix above. A GitHub release for that tag is not published at the time of this check, so package/release availability is not yet confirmed. The fix is included in v0.2.583 source.

Sign in to comment on this issue.