AJAX and the no-JavaScript fallback
With JavaScript (default, 'ajax' => true)
AJAX here means fetch, through WordPress's own @wordpress/api-fetch (the
same request layer as the block editor and CAFE's React admin), not jQuery's
$.ajax. Turn it off per form with 'ajax' => false or, in CAFE → Forms, the
Send Without Reloading toggle.
Forms are sent with fetch (WordPress apiFetch, no jQuery) to
POST /cafe/v1/forms/submit. While sending, the button is disabled and the
form has .is-submitting and aria-busy="true". Then:
- Saved: the success message appears (create forms hide their fields), or the browser goes to the form's redirect.
- Not saved: messages appear under the fields and at the top; the first field with a problem gets focus. Everything typed stays.
- No answer (network): "The form could not be sent…". Sending again is safe: the submission key makes sure one submission is saved once.
After each attempt the form fires a DOM event you can listen to:
document.addEventListener( 'cafe-form-submitted', ( event ) => {
const result = event.detail; // { success, object_id, field_errors, form_errors, message, redirect }
if ( result.success && event.target.id === 'cafe-form-new-event' ) {
window.dataLayer?.push( { event: 'event_submitted' } );
}
} );
Without JavaScript
The form is a normal HTML form (method="post") and works without
JavaScript, or with 'ajax' => false:
- The browser posts to the same page.
- CAFE handles it early (
template_redirect), with the same checks. - Saved: a redirect (303) to the form's redirect, or to the same page
with
?cafe_form={id}&cafe_saved=1, which shows the success message. A page reload never sends the form again. - Not saved: the same page shows the messages and what was typed.
Pickers, media, Collections' add/remove buttons and the rich text editor need JavaScript; plain inputs do not.
Turning AJAX off
cafe_dynamic_form( [ 'id' => 'new-event', 'ajax' => false, /* … */ ] );
Useful when other scripts on the page expect a real page load after sending.