Skip to content

feat: add event-driven validation plugin (SmarkForm.createValidation)#145

Draft
Copilot wants to merge 4 commits intomainfrom
copilot/add-validation-plugin
Draft

feat: add event-driven validation plugin (SmarkForm.createValidation)#145
Copilot wants to merge 4 commits intomainfrom
copilot/add-validation-plugin

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 31, 2026

  • Add ## Complete Interactive Example section to docs/_advanced_concepts/validation.md
    • HTML: date-periods list (start_date/end_date per row), ➕/➖/▶ Export buttons, <ul id="msgs"> message area, <pre id="out"> export display
    • CSS: .period-row flex layout, [aria-invalid="true"] red border/background, .sf-issue.error/.warning styled message items, scoped to #myForm$$
    • JS: checkDateOrder provider (per-period date order), checkNoOverlap provider (overlap detection between sorted periods), ValidationStateChanged handler for inline messages, AfterAction_export handler for export output
    • demoValue: two valid 2025 half-year periods for a clean initial state
    • sampletabs_tpl.md include: showEditor=true, selected="preview", height=55, tests=false
    • Hint note explaining ValidationStateChanged vs ValidationIssuesChanged
  • Updated TOC in validation.md to include * [Complete Interactive Example]
  • All 1385 tests pass (1375 previous + 10 new: smoke test + demoValue round-trip × 4 browsers for the new example)
Original prompt

Implement an initial, minimal validation plugin for SmarkForm, aligned with the library’s event-driven philosophy.

Repository: bitifet/SmarkForm

Goal

Create a first iteration of a validation system that can:

  • Attach to a SmarkForm root instance.
  • Validate on form change (debounced), and also validate before export.
  • Accept one or more validation providers (sync or async).
  • Maintain validation state and diff it between runs.
  • Emit events for validation state changes and for issue changes.
  • Apply ARIA side effects by default (aria-invalid for errors), in a preventable way.

This is meant as a baseline to iterate on.

Design constraints / philosophy

  • Keep core component types (input/date/list/etc.) unchanged as much as possible.
  • Prefer an add-on module under src/lib (or similar) rather than embedding validation logic into all types.
  • Use SmarkForm’s existing event system: listen to bubbling field change events (and potentially others) from the root.
  • Use SmarkForm paths as canonical issue paths (must use the same syntax as component.getPath()).

Functional requirements

1) Public API

Add a new module that exports something like:

  • createValidation(root, options) or new SmarkValidation(root, options).
  • It should return an object with at least:
    • validate(reason?) (force validation immediately)
    • getState() (current issues, hasErrors/hasWarnings)
    • destroy() (remove listeners)

2) Provider interface

Providers should be passed in via options and have a uniform signature:

  • (ctx) => { issues } | Promise<{ issues }>
  • ctx should include at least { root, data, reason, changedPaths?, signal? }.

3) Issues model

Implement an Issue object with:

  • id (stable string)
  • level: at least error|warning
  • paths: array of SmarkForm paths (at least one path)
  • code, message, source (strings)
  • details (optional)

Implement default id generation: ${source}:${code}:${paths.join('|')}.

4) Diffing

Store previous issues by id and compute:

  • newIssues
  • solvedIssues
  • persistingIssues
    (Optionally track changed issues, but not required for first iteration.)

5) Events emitted

Emit validation events through SmarkForm’s .emit mechanism so they bubble (root-level).
Proposed events:

  • ValidationStateChanged
  • ValidationIssuesChanged
    Each event should include the current issues and at least newIssues and solvedIssues.

Also implement a dedicated, preventable side-effect event:

  • BeforeValidationA11yApply and/or allow ValidationStateChanged to be preventable for ARIA application.

6) ARIA side effects

By default:

  • Apply aria-invalid="true" on targetFieldNode for any component path that currently has at least one error issue.
  • Remove aria-invalid when errors are solved.
    Warnings should not set aria-invalid.

Make this preventable via event cancelation so developers can override the behavior.

7) BeforeAction_export blocking

Hook into BeforeAction_export on the root:

  • Run validation.
  • If there are any error issues, call preventDefault() to block the export.
    (Provide an option to disable this behavior.)

8) Documentation + example

Add minimal docs in docs/_advanced_concepts/ (or another appropriate place) describing:

  • How to create validation providers.
  • How to attach validation to a form.
  • How to listen to validation events.
  • Example provider using a simple custom rule (e.g., start/end date ordering) to demonstrate partial/cross-field issues.

Optionally add a small docs example snippet that is included in the documentation testing framework.

9) Tests

Add at least a small Playwright test that:

  • Loads a docs example or a minimal HTML page.
  • Attaches validation.
  • Triggers changes.
  • Asserts that ValidationStateChanged is fired and aria-invalid is toggled.
  • Asserts export is blocked when errors exist (if enabled).

Implementation notes

  • Place new code under src/lib/validation/ (or similar) and wire it into build.
  • Keep changes minimal and reversible.
  • Ensure npm test passes.

Deliverables

  • New validation module implementation.
  • Documentation page and/or docs example.
  • Tests covering basic behavior.

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: Please review your AGENTS.md file and the rest of information you have under the AGENTS directory and then examine the codebase under the src directory to get a full understanding of how SmarkForm works and which is its philosophy.

You can also read the documentation under the docs directory for mor information.

When you have a full understanding on how everything works and how the library breaths, I want you to, following the same philosophy, propose a good and solid plan to approach form validation aids.

Our goal is to allow integration with common validation tools like zod taking in account both partial and full validation.

By partial, I mean if, for instance, we want to give feedbac...

This pull request was created from Copilot chat.

Copilot AI and others added 2 commits March 31, 2026 22:04
Copilot AI changed the title [WIP] Add initial validation plugin for SmarkForm feat: add event-driven validation plugin (SmarkForm.createValidation) Mar 31, 2026
Copilot AI requested a review from bitifet March 31, 2026 22:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants