Skip to content

Instantly share code, notes, and snippets.

@Striffly
Last active October 15, 2025 12:58
Show Gist options
  • Save Striffly/fa79b85901dd6c98a8075a35d7dc45ee to your computer and use it in GitHub Desktop.
Save Striffly/fa79b85901dd6c98a8075a35d7dc45ee to your computer and use it in GitHub Desktop.
Gravity Forms with AJAX, conditional logic, pages transitions (compatible with Barba.js, Taxi.js, Highway.js, ...)

The following code enables the use of Gravity Forms (2.8.7 as of now) with the following features:

  • AJAX loading, 100% functional
  • Functional with page transitions (Barba.js, Taxi.js, Highway.js)
  • Enqueue Gravity Forms scripts used by each forms (including conditional logic scripts)
  • Works with recaptcha (with recent version of Gravity Forms reCAPTCHA Add-On, scripts are automaticaly enqueued)
  • Keep the form displayed after submission (optional)
  • Scripts moved to footer (optional)

The code was initially integrated into projects using roots/sage. I adapted the code for integration into "vanilla" WordPress projects but I have less feedback compared to the use I have with my stack, so feel free to let me know if there are any errors in the comments!

<div class="js-gravity-form" data-id="<?php echo $formId ?>">
<?php if (is_admin()) {
echo gravity_form($formId, false, false, false, false, false, 0, false);
}
?>
</div>
// import { ScrollTrigger } from 'gsap/ScrollTrigger';
class Forms {
constructor() {
if (typeof jQuery === 'undefined') return;
this.events();
this.loadForms();
}
events() {
document.addEventListener('gform_main_scripts_loaded', () => {
if (typeof gform === 'undefined') return;
gform.scriptsLoaded = !0;
this.loadForms();
});
// (optional) Hooks related to form display after form submit
jQuery(document).on('gform_post_render', (event, form_id, current_page) => {
const formEl = document.querySelector(`.js-gravity-form.loaded[data-id="${form_id}"]`);
if (formEl) {
// Remove confirmation messages after form submit
if (formEl.classList.contains('submitted')) {
formEl.classList.remove('submitted');
} else {
const confirmationMessagesContainer = formEl.querySelector('.gform_confirmation_wrapper');
if (confirmationMessagesContainer) {
confirmationMessagesContainer.remove();
}
}
// Remove empty divs after form submit
const emptyDivs = formEl.querySelectorAll('.gform_custom_empty_div');
emptyDivs.forEach((emptyDiv) => {
emptyDiv.remove();
});
}
});
// (optional) Show form again after form submit
jQuery(document).on('gform_confirmation_loaded', (event, formId) => {
const ev = new CustomEvent('gform_submitted', { detail: { event, formId } });
window.dispatchEvent(ev);
const formEl = document.querySelector(`.js-gravity-form.loaded[data-id="${formId}"]`);
if (formEl) {
formEl.classList.add('submitted');
const fields = formEl.querySelector('form').querySelectorAll('input:not([type=submit]):not([type=hidden]), textarea, select');
fields.forEach((input) => {
if (input.type === 'radio' || input.type === 'checkbox') {
input.checked = '';
} else {
input.value = '';
}
});
const wrapper = formEl.querySelector('.gform_wrapper');
wrapper.style.removeProperty('display');
this.loadFormHooks(formId);
}
});
}
loadForms() {
if (typeof gform === 'undefined' || !gform.scriptsLoaded || !gform.domLoaded) return;
const formContainers = document.querySelectorAll('.js-gravity-form');
for (const formContainer of formContainers) {
if (formContainer.classList.contains('loaded')) continue;
formContainer.classList.add('loaded');
const formId = formContainer.dataset.id;
fetch(`${wp_vars.adminAjax}?action=gf_get_form&form_id=${formId}`, {
method: 'GET',
credentials: 'same-origin',
})
.then((res) => res.json())
.then((datas) => {
const html = datas.data;
jQuery(formContainer).html(html);
this.loadFormHooks(formId);
// use it if you are using ScrollTrigger, ScrollSmoother, etc.
// ScrollTrigger.refresh();
const ev = new CustomEvent('gform_loaded', { detail: { formId } });
window.dispatchEvent(ev);
});
}
}
loadFormHooks(formId) {
jQuery(document).trigger('gform_post_render', [parseInt(formId), 0]);
if (window.gformInitDatepicker) {
window.gformInitDatepicker();
}
if (window.gformInitPriceFields) {
window.gformInitPriceFields();
}
}
}
document.addEventListener("DOMContentLoaded", function() {
gform.domLoaded = !0;
new Forms();
});
<?php
// [...]
/** GRAVITY FORMS RELATED FUNCTIONS & HOOKS **/
/**
* Open numeric keypad on mobile for number fields in gravity forms
* https://wire.gravityhopper.com/d/35-open-numeric-keypad-on-mobile-for-number-fields
*/
add_filter('gform_field_content', function ($content, $field, $value, $lead_id, $form_id) {
if (wp_is_mobile() && ($field instanceof GF_Field_Number || $field instanceof GF_Field_Quantity)) {
$content = str_replace("type='", "inputmode='decimal' type='", $content);
}
return $content;
}, 10, 5);
/**
* Disable the native auto-scroll feature on form errors
*/
add_filter('gform_confirmation_anchor', '__return_false');
/**
* Force add Gravity Forms hooks to all pages
*/
add_filter( 'gform_force_hooks_js_output', '__return_true' );
/**
* (optional) Allow the Gravity form to stay on the page when confirmation displays.
* Forked from https://gist.github.com/davidwolfpaw/0fa37230c9dbb197ed4a8bbc1c7e9547
*/
add_filter('gform_pre_submission_filter', 'gf_show_confirmation_and_form');
function gf_show_confirmation_and_form($form)
{
// Inserts a shortcode for the form without title or description
$shortcode = '[gravityform id="' . $form['id'] . '" title="false" description="false" ajax="true"]';
// Ensures that new lines are not added to HTML Markup
ob_start();
echo do_shortcode($shortcode);
$html = str_replace(array("\r", "\n"), '', trim(ob_get_clean()));
$html = preg_replace('#<script(.*?)>(.*?)</script>#is', '', $html);
$html = preg_replace('#<iframe(.*?)>(.*?)</iframe>#is', '', $html);
// Inserts the form into parent div
if (array_key_exists('confirmations', $form)) {
$lastKey = array_key_last($form['confirmations']);
$form['confirmations'][$lastKey]['message'] = $form['confirmations'][$lastKey]['message'] . '</div></div>' . $html . '<div class="gform_custom_empty_div"><div>';
}
return $form;
}
/**
* (optional) Move Gravity Forms scripts to footer
*/
add_filter('gform_init_scripts_footer', 'gform_init_scripts');
function gform_init_scripts() {
return true;
}
/** AJAX **/
add_action('wp_ajax_nopriv_gf_get_form', 'gf_ajax_get_form');
add_action('wp_ajax_gf_get_form', 'gf_ajax_get_form');
function gf_ajax_get_form()
{
if (!isset($_GET['form_id'])) {
wp_send_json_error();
exit;
}
$formId = absint($_GET['form_id']);
wp_send_json_success( gravity_form($formId, false, false, false, false, true, 0, false) );
exit;
}
/** ENQUEUE SCRIPTS */
function get_wp_variables() {
return [
'adminAjax' => admin_url('admin-ajax.php'),
];
}
wp_enqueue_script(
'forms',
get_stylesheet_directory_uri() . '/forms.js',
array( 'jquery' )
);
wp_localize_script( 'forms', 'wp_vars', $get_wp_variables );
@Kaki-In
Copy link

Kaki-In commented Oct 15, 2025

Hi @gonzalo-terrahq

I'm also trying to mix Swup and Gravity Forms together and I can't make it handle the "Next" button (multipage form).

When I start directly from the page which includes the form, it works perfectly, I can click on Next, Previous, etc... and the pages load perfeclty.

When I start from another page and navigate to the form, the Next button doesn't seem to do anything,
but after searching a bit more I noticed that it seems it is only about the navigation : after having pressed a second time the Next button, I get this error :
image

Did you get multipage form navigation to work?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment