Skip to content

The JS helper

You write the form’s HTML. The helper takes care of everything else: fetching the security token, sending the submission, retrying when it should, and showing validation errors next to the right fields. It is part of the frontend bundle that always loads, so there is nothing extra to enqueue.

Add data-octa-forms="slug" to your <form>, and the helper binds to it automatically:

<form data-octa-forms="contact" enctype="multipart/form-data">
<input type="text" name="name" />
<input type="text" name="email" />
<label><input type="checkbox" name="consent" /> I agree to be contacted</label>
<input type="file" name="cv" accept=".pdf,application/msword" />
<!-- honeypot field, see Anti-spam -->
<button type="submit">Send</button>
</form>

A few notes on that markup:

  • The name of each input must match a field name in the form’s config.
  • enctype="multipart/form-data" only matters for a no-JavaScript fallback. The helper submits with fetch and sets the correct content type itself.
  • accept is only a hint to the browser. The server checks the real file type by inspecting the contents.
  1. Fetches a security token on the visitor’s first interaction with the form, so pages that are only viewed cost nothing.
  2. Sends the submission to the REST API in the correct format, including any uploaded file.
  3. Handles the token’s retry cases automatically (for example, a submit that came in suspiciously fast).
  4. On success, shows the thank-you message or follows the configured redirect.
  5. On failure, places each validation message next to its field.

You never have to touch the token or the request format. If you do want that level of control, see Your own JavaScript.

The helper renders validation errors as:

  • span.octa-forms-error next to the field that failed.
  • div.octa-forms-error--form at the top of the form, for errors that are not tied to one field.

Styling those is up to your theme.

On success or failure the form fires an event you can hook analytics or custom behaviour onto:

form.addEventListener('octaforms:success', (e) => {
// e.detail carries the submission result
});
form.addEventListener('octaforms:error', (e) => {
// e.detail carries the error
});

The helper scans for form[data-octa-forms] once, when the page’s DOM is ready. A form you insert later, for example one revealed in a modal or cloned from a template, will not be picked up on its own. Bind it by hand:

const form = modal.querySelector('form[data-octa-forms="contact"]');
window.octaForms.attach(form); // safe to call twice; returns the instance or null

attach() is available as soon as the bundle loads. It is idempotent, guarded by a data-octa-forms-bound attribute, and only binds elements that carry data-octa-forms. This is exactly how the callback widget works internally.

The automatic scan can be switched off with the octa_forms_helper_autobind filter (there is no admin setting for it). When off, the helper skips the initial scan but window.octaForms.attach() still works, so you bind forms yourself. This is for cases where all your forms are inserted dynamically. A shortcode on the page forces the scan back on for its own form.

To remove the plugin’s JavaScript entirely instead, see Frontend assets.

The forms rendered by the shortcode and the callback widget use the same stable classes, all in the octa-forms namespace, so your theme can style them:

Selector Element
form.octa-forms The form container (also carries data-octa-forms="slug")
.octa-forms__field A field wrapper (plus a type modifier, e.g. .octa-forms__field--checkbox)
.octa-forms__actions / .octa-forms__submit The actions row and the submit button
.octa-forms__thank-you The thank-you screen shown after a successful submit
.octa-forms__noscript The message shown when JavaScript is off
.octa-forms-error / .octa-forms-error--form A field error / a form-level error