Skip to content

Forms & markup ​

submito works with the form you already have. It reads values, writes error text, and toggles a few attributes. You style everything.

What submito changes on the form ​

WhenChange
newForm()novalidate on the form (browser bubbles are replaced by inline messages). Restored by destroy().
Field invalidaria-invalid="true" + aria-describedby on the control, class error on its wrapper, a message element.
Request runningaria-busy="true" on the form, submit buttons disabled, indicator shown.
Success (built-in UI)form.reset(), unless resetOnSuccess: false.

Fields ​

Every field you want to send needs a name. submito builds the payload with the browser's own new FormData(form), so the rules are the native ones:

ControlSent
text, email, tel, number, date, hidden, …the value
selectthe selected value(s); multiple sends one entry per option
textareathe value
checkbox / radioonly when checked
fileeach selected file; empty file inputs are dropped
the clicked submit buttonits name=value, if it has a name
disabled fieldsnothing

Fields outside the <form> tag but linked with form="form-id" are included. Use bracket names (tags[], user[email]) if your backend expects arrays or nested fields.

Where error messages go ​

By default submito appends a message to the field's parent element:

html
<label class="field error">
  Email
  <input name="email" type="email" aria-invalid="true" aria-describedby="submito-error-1" />
  <span class="error-message" id="submito-error-1">Please enter a valid email address.</span>
</label>
  • Wrap each control in its own element (a <label> or <div>) so the message lands next to it.
  • A group of radios or checkboxes that each sit in their own <label> gets one message on the group's container.
  • The intl-tel-input wrapper (.iti) is skipped, so the message goes below the phone field.

Custom placement ​

Put an element with data-submito-error="<field name>" anywhere in the form, and submito writes into it instead:

html
<div class="row">
  <input name="email" type="email" required />
  <button>Subscribe</button>
</div>
<p class="form-hint" data-submito-error="email"></p>

submito never removes your element. It only sets and clears its text, so you can style the empty state with :empty.

Styling ​

css
.error-message {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.875rem;
  color: #b00020;
}

[aria-invalid="true"] {
  border-color: #b00020;
}

.error > label,
.error .label {
  color: #b00020;
}

form[aria-busy="true"] {
  cursor: progress;
}

Error text is always set with textContent, never as HTML.

Loading indicator ​

html
<button type="submit">Send</button>
<span id="sending" hidden>Sending…</span>
js
submito.newForm({ form: '#contact', indicator: '#sending' });

See Configuration → indicator for the class rules (hidden, uk-hidden, d-none).

Multiple forms ​

Call newForm once per form:

js
submito.newForm({ form: '#newsletter' });
submito.newForm({ form: '#contact', indicator: '#contact-sending' });

Each instance is independent. Events are dispatched on their own form element, so listeners never need to filter by id unless they listen on document.

Forms added later ​

Call newForm after the form exists in the DOM, for example after you inject it or when your component mounts. When you remove it again, call form.destroy(). Calling newForm twice on the same form element replaces the old instance.

Released under the MIT License.