RRenDSv0.14.1

Pattern

Form Validation Requires JS

Conventions for inline error messages, summary banners, and submit-button state. Browser-native HTML5 validation does most of the work; this pattern documents how to wire the rest.

About

Overview

Form validation is a pattern, not a component — it's how Field, Banner, Button and Toast cooperate when a form is wrong or submitted. Use HTML5 attributes (required, type, pattern, min, max) for client-side; show server-side errors via setError() on each Field.

Live

Demo

Submit with the fields empty: ren-form validates, fills the error summary, focuses it, and wires each message to its field.

<ren-form data-validate="onSubmit">
  <form class="ren-form" novalidate>
    <div class="ren-form-error-summary" role="alert" tabindex="-1" hidden>
      <strong>Please fix the following errors:</strong>
      <ul></ul>
    </div>

    <ren-field data-rules="required|email">
      <label>Email</label>
      <input class="ren-input" type="email" name="email" required>
      <span data-error></span>
    </ren-field>

    <div class="ren-form-actions">
      <button class="ren-btn ren-btn-primary" type="submit">Save</button>
    </div>
  </form>
</ren-form>

Patterns

Pieces

  • HTML5 attributes: required, type="email", pattern, min, max, minlength, maxlength.
  • Per-field errors: Form Field shows aria-invalid + the error message.
  • Form-level summary: an empty .ren-form-error-summary with role="alert" and tabindex="-1" at the top of the form. ren-form fills it with one link per error, focuses it, and hides it again once the form validates (skip-to-error pattern).
  • Server-side errors: after a failed submit, call field.setError(message) for each invalid field.
  • Submit button state: ren-form sets data-submitting on the host and disables the submit buttons while an async ren-submit consumer is in flight. Don't disable the button proactively before the user types — it's confusing.

Variant

Multi-step forms

Use a multi-step form when a single page would feel overwhelming or when steps depend on previous answers. ren-form supports multi-step via the data-steps attribute on the host and a .ren-stepper progress indicator.

  1. Account
  2. 2Profile
  3. 3Plan

Step 2 of 3 — current step content goes here.

<ren-form data-steps="3">
  <ol class="ren-stepper" aria-label="Setup progress">
    <li data-completed>Account</li>
    <li aria-current="step">Profile</li>
    <li>Plan</li>
  </ol>
  <fieldset data-step="1">…</fieldset>
  <fieldset data-step="2" data-active>…</fieldset>
  <fieldset data-step="3">…</fieldset>
</ren-form>

Stepper API

Class / attributeEffect
.ren-stepperThe progress indicator. Numbered ol with completed / current / pending states.
[aria-current="step"]Marks the active step.
[data-completed]Marks a past step (checkmark fill).
[data-steps="N"] on hostDeclares the total number of steps.
[data-active] on fieldsetMarks the currently visible step; others are hidden.

Pattern checklist

  • Validate the current step before Next advances.
  • Allow free Back navigation — don't lose prior data.
  • Save progress to localStorage or the server so the user can leave and resume.
  • Last step is "Review" — show all entered data before final submit.
  • Autofocus the first input on each step change.
  • Announce progress via a polite live region: "Step 2 of 3."

Status of .ren-stepper: the stepper is an internal CSS pattern of ren-form, not a standalone component. There is no ren-stepper primitive, Web Component, or separate JS — it's a styled <ol> that consumer code drives. If you need a reusable Stepper outside a multi-step form (e.g. an onboarding tour, or a wizard not tied to a single form), open an issue — it's on the backlog.

Inclusive by default

Accessibility

  • Use novalidate on the form so you control validation timing instead of letting the browser show its own popup before submission.
  • Validate on blur (not on every keystroke) for first-time entry; revalidate on input after the field has been marked invalid once.
  • Move focus to the first invalid field after a failed submit.
  • Summary banner uses role="alert" so screen readers announce the error count immediately.
  • For multi-step flows: each step is its own <fieldset> with its own focus management; the stepper uses aria-current="step" on the active item.