Skip to content

Forms & markup

formsub works with a plain HTML form. You style it; formsub only reads values and writes error text.

Form element

html
<form id="contact-form">
  <!-- fields -->
</form>

The id must match formId. Native action and method are ignored — submission goes through fetch to ajaxUrl.

Field naming

Every submitted field needs a name:

html
<input name="email" type="email" required />
<select name="topic">...</select>
<textarea name="message"></textarea>

Wrap the control in a <label> so the error <span> lands next to the field:

html
<label class="field">
  Email
  <input name="email" type="email" required autocomplete="email" />
</label>

Supported controls

ControlWhat is sent
text, email, tel, hidden, number, …Current value
select, textareaCurrent value
checkbox, radioSent only when checked
fileSelected files; empty file inputs are skipped
submit, button, reset, imageSkipped

File uploads

html
<form id="upload-form" enctype="multipart/form-data">
  <input name="attachment" type="file" accept=".pdf,.png" />
</form>

enctype is optional for FormData + fetch, but it documents intent. Always validate type and size on the server — accept is only a hint.

Checkboxes

html
<label>
  <input type="checkbox" name="terms" value="1" required />
  I agree to the terms
</label>

Unchecked boxes are omitted from FormData.

Field errors

On validation failure (client or server), formsub inserts:

html
<span class="error-message">This field is required</span>

inside the field's parent and may add class error:

html
<label class="error">
  Email
  <input name="email" type="email" />
  <span class="error-message">Invalid email address</span>
</label>

Error text is set with textContent, not innerHTML. Style the classes in your CSS:

css
.error-message {
  color: #b00020;
  font-size: 0.875rem;
}

label.error input,
label.error select,
label.error textarea {
  outline: 1px solid #b00020;
}

Loading indicator

html
<button type="submit" id="submit-button">Send</button>
<p id="loading" class="hidden">Sending…</p>
js
indicator: '#loading'

See Configuration for the class toggling rules.

Math captcha

html
<input name="numb_captcha" type="text" required autocomplete="off" />

formsub sets a placeholder like 3 + 7 = ? and injects hidden num1 / num2 fields. Details are on Validation.

Multiple forms

Call newForm once per form, each with its own formId:

js
formsub.newForm({
  formId: 'newsletter-form',
  submitButton: '#newsletter-submit',
  ajaxUrl: '/api/newsletter',
});

formsub.newForm({
  formId: 'contact-form',
  submitButton: '#contact-submit',
  ajaxUrl: '/api/contact',
});

Window events are shared. Filter by event.detail.form_css_id if you listen globally — see Events & callbacks.

Released under the MIT License.