UPDATE 22 May 2021: The plugin has been updated to work with Gravity Forms 2.5.2.4
If you read my post last week, which demonstrates how to display Gravity Forms in WordPress admin pages, it may have got you thinking about all the possibilities it opens up. Perhaps you realised that it’s also possible to load Gravity Forms via WordPress AJAX since that also runs in the admin context.
Of course Gravity Forms has long supported AJAX-enabled forms with the shortcode, but what if you don’t know which form to load until the user selects an option from a list? Or perhaps you only want to load the form only if a certain button is clicked? In this case the form has to be loaded via AJAX not during the first page request.
I’ve put together a rudimentary plugin to demonstrate how to load Gravity Forms via WordPress AJAX. It renders a button along with an empty container ready for the form. When the button is clicked the form is loaded into the container. It supports multiple forms both in admin and in front-end pages.
Here’s an example of how to use it followed by a functioning implementation.
[gravityforms action="button" id=1 text="Load the contact form"]
Notice the sense of tighter integration with Gravity Forms that comes from using the core [gravityforms] shortcode instead of inventing a new one.
A couple of caveats:
1. The single file upload field won’t work but the multi-file field will.
2. Remember this is just a demonstration and a proof of concept intended to help point you in the right direction. If you intend to use the code in a production environment please adjust it according to your needs.
The complete plugin is on GitHub if you’d like to follow or fork it.
If you find this useful, or if you implement a different twist on the idea, please do let me know in the comments below.
Thanks, this was pretty handy!
I am having an issue, though. If I load the form a second time (via ajax, without reloading the page,) the form action is different, and the form will not send.
When my page first loads, it uses the gravity_form() function to get my form into the page, and the form action is “/new/#gf_2”
Sending from this form works.
Then if I reload the form via ajax (which uses the same gravity_form() call and loads the results into the right element on my page) I get the exact same form, but the action is “/wp-admin/admin-ajax.php#gf_2”
Sending using this second form does not work (returns 0, actually, in response.)
Do you have any clues on this?
Thanks.
I’ve not been able to reproduce this problem I’m afraid. Sent you a mail.
i’m loving this solution and is coming in very handy. But for some reason, a date field in the returned ajax form doesn’t pop-up the date picker. if i submit and get a required field error, then i can get the date-picker to pop-up.
i’m wondering if there is anything i can do to get it to work.
The date picker needs to be initialised. I’ve updated the snippet and the github repo to support the date picker.
thats awesome! works great! thanks
Hi, this is what I’m looking for I think. I want it to open in a popup window ajax style. I want to use on my pricing tables for the “buy now” button. So they click the buy now button and a popup window opens with a field for them to enter a URL and also one for entering a discount coupon code. How do I implement it into my site like that?
I modified the script to launch the form in a vex popup:
$.get('{$ajax_url}?action=gf_button_get_form&form_id={$form_id}',function(response){
vex.open({
content: response
});
// $('#gf_button_form_container_{$form_id}').html().fadeIn();
button.remove();
if(window['gformInitDatepicker']) {gformInitDatepicker();}
});
Vex is already present and loaded by the theme. HTH!
That looks great – thanks for sharing.
This is AWSOME. Exactly what I needed. I just modified the script a bit to launch the Gravity Form in a Vex modal. Thanks!
This is awesome. I tweaked your script a little to launch gravity forms in a modal window and it worked brilliantly.
Thanks for the feedback Jonathan.
Hi Steven,
Great inside. However, we have tried to do the same. On first time load we load in the needed script files with gravity_form_enqueue_scripts, then we load the needed page through WP ajax and print it onto the body, the page includes the form using gravity_form. The form is added fine but when submitting the form, the form doesn’t validate properly and the json response is 0. Any idea what might go wrong?
Example here btw:
http://www.connekt.nl/events/test-event/
Does my sample plugin work on your site?
Hi Steven,
Thanks for your reply. After trying your snippet it worked! Which surprices me. After debugging we finally found the problem which is worth mentioning to those who did not know, Gravity Forms will take your get or post request as the action for it’s form. So where it went wrong with us, is that we did a get request to get out page, but the form was going to do the same, requesting the entire page, instead of only the form. So we changed that by adding a second ajax call, just for the form. Now it works like your example!
As long as you have ajax enabled in the form you shouldn’t need a second call. https://www.gravityhelp.com/documentation/article/embedding-a-form/#function-call
Does that help?
Hi Steven,
We got it solved, however, after we loaded an form in with this ajax solution that has conditional logic in it, it says: “gf_apply_rules is not defined”. Any clue how to solve this?
Thnx, Harro
Same issue seems to happen with “gwrf is not defined”
Hello Steven,
nice article, it helped 🙂
Best,
Chris.
Thanks Chris!
Here’s a mod to prevent admin labels from showing instead of the correct ones and to load the form in a fancybox modal:
add_action( 'wp_ajax_nopriv_gf_button_get_form', 'gf_button_ajax_get_form' );
add_action( 'wp_ajax_gf_button_get_form', 'gf_button_ajax_get_form' );
// Add the "button" action to the gravityforms shortcode
// e.g. [gravityforms action="button" id=1 text="button text"]
add_filter( 'gform_shortcode_button', 'gf_button_shortcode', 10, 3 );
function gf_button_shortcode( $shortcode_string, $attributes, $content ){
$a = shortcode_atts( array(
'id' => 0,
'text' => 'Show me the form!',
), $attributes );
$form_id = absint( $a['id'] );
if ( $form_id < 1 ) {
return 'Missing the ID attribute.';
}
// Enqueue the scripts and styles
gravity_form_enqueue_scripts( $form_id, true );
$ajax_url = admin_url( 'admin-ajax.php' );
$html = sprintf( '%s', $form_id, $a['text'] );
$html .= sprintf( '', $form_id );
$html .= "
(function (SHFormLoader, $) {
$('#gf_button_get_form_{$form_id}').click(function(){
var button = $(this);
$.get('{$ajax_url}?action=gf_button_get_form&form_id={$form_id}',function(response){
$.fancybox.open({
content: response
});
if(window['gformInitDatepicker']) {gformInitDatepicker();}
});
});
}(window.SHFormLoader = window.SHFormLoader || {}, jQuery));
";
return $html;
}
$form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0;
add_filter('gform_pre_render_'.$form_id, 'fix_admin_labels');
function fix_admin_labels($form){
foreach($form['fields'] as $i=>$field) {
if(isset($field['adminLabel'])){
$field['adminLabel'] = $field['label'];
}
}
return $form;
};
function gf_button_ajax_get_form(){
global $form_id;
gravity_form( $form_id,true, false, false, false, true );
die();
}
Hi Steven,
Is there a way to have the button follow the styles set out by the theme? It seems that right now it produces a basic button. Love the plugin btw. Thanks
Really helpful code, thank you! One variation I’ve added is to separate the button build into its own function, which can be called by the shortcode filter or echoed into a template. Super helpful for a current project.
Thanks for that plugin, it looks just what I needed. I entered the shortcode in the notification text of the form so that the button appears after the notification message. The problem here is that once the button is pressed the notification message keeps being visible and all form styles have inherited the notification message styles! Then when the form gets submited another notification message gets added under the first one! Is there a way for the button to make the form load on top of the notification message thus replacing it and start with a new form but obviously without refreshing the page?
Hi Steve,
Is it possible to get this to also populate a drop down set to dynamically populate.
Here’s a crude example of what i’m trying to attempt, http://bit.ly/1qAStZC.
I’d like to already have the form loaded on a page and have someone click a link to update a dropdown on the form, they would then click another link to update another dropdown on the form.
The way I have it set up the user clicks the link it takes them to an anchor of the page where the form is with their input chosen, however if they go back to the top and choose another link when they return to the anchor with the form the new option is selected but the old one has returned to its’ default value.
Hi,
Thank so much for the snippet, it works!
I am however trying to add links to buttons in my pricing table.
Is there a way to retrieve the link only, so i can add it to my pricing table’c button url.
Hi Steve,
Thanks for distributing your plugin.
Do you know how to send a drop down value to another page with ajax in gravity forms? so, via that value we can decide which gravity view to load. I tried tweaking gravityforms.php, but couldn’t make it. Also, couldn’t specify an action for the form. Please advise which file should be tweaked. Thanks
Steven,
I’ve been searching for solution on how to load my Gravity forms everytime a user changes the option in my `WooCommerce` variable product `dropdown`?
The Gravity form will depend on the variation id of `WooCommerce`.
I am able to pull and display the variation Id in my product page. The problem is I don’t know how to load the form via AJAX.
//This is my JS
jQuery(document).ready(function($){
$( document ).on( “found_variation.first”, function ( e, v ) {
//console.log(“inside JS “+ v.variation_id );
var varid = v.variation_id;
var ajaxurl = object.ajaxurl;
var data = {
action: ‘my_action’,
var_id : varid,
};
$.post(ajaxurl, data, function(response) {
$((‘div.woocommerce-variation-add-to-cart’)).html(response);
class=”selected-variation-id”>’+response+”);
});
} );
});
This is my functions.php
wp_register_script( ‘my-fffjquery-script’, get_template_directory_uri() . ‘/js/my-fffjquery-script.js’, array( ‘jquery’ ), ‘1.0.0’, true );
wp_localize_script( ‘my-fffjquery-script’, ‘object’, array( ‘ajaxurl’ => admin_url( ‘admin-ajax.php’ ) ) );
wp_enqueue_script( ‘my-fffjquery-script’);
add_action( ‘wp_ajax_my_action’, ‘my_action_callback’ );
add_action( ‘wp_ajax_nopriv_my_action’, ‘my_action_callback’ );
function my_action_callback(){
$passedvariationid = $_POST[‘var_id’];
global $form_id;
echo $passedvariationid; // will be ‘response’ in ajax
$form_id = ‘9’;
gravity_form( $form_id,true, false, false, false, true );
die();
Hello!
Thanks for this plugin!
Cheers
Hi Steven
Awesome work!
Have implementet the Popup solution you provided above, and everything works. But what if you have two buttons on the same page, to the same form?
I have moved the ID value to a class value and wrapped it in a jQuery.each(). But when I click the button, two popups appear (with two instances of the button on the page)
Here’s the code:
function gf_button_shortcode($shortcode_string, $attributes, $content)
{
[… code left out intentionally… ]
$html = sprintf(‘%s’, $form_id, $a[‘button_class’], $a[‘text’]);
$html .= sprintf(”, $form_id);
$html .= ”
(function (SHFormLoader, $) {
$(‘.gf_button_get_form_{$form_id}’).each(function(index){
$(this).click(function(){
$.get(‘{$ajax_url}?action=gf_button_get_form&index=’+index+’&form_id={$form_id}’,function(response){
console.log(response);
lity(response);
if(window[‘gformInitDatepicker’]) {gformInitDatepicker();}
});
});
});
}(window.SHFormLoader = window.SHFormLoader || {}, jQuery));
“;
return $html;
}
Cheers!
Jeppe R.
thank you it working fine 🙂
Nice example!
For the record, if you’re using the built-in Google reCAPTCHA, you have to enqueue the api script: https://www.google.com/recaptcha/api.js
This should be enqueued at the same time as you run gravity_form_enqueue_scripts.
You also need the following (from GF_Field_CAPTCHA::ensure_recaptcha_js() )
jQuery( document ).bind( 'gform_post_render', function() {
var gfRecaptchaPoller = setInterval( function() {
if( ! window.grecaptcha || ! window.grecaptcha.render ) {
return;
}
renderRecaptcha();
clearInterval( gfRecaptchaPoller );
}, 100 );
} );
That’s very helpful – thanks Mike!
Please i need more explanation about how to use google recaptcha. What do I have to do ?
Could you explain detail to resolve this issue? I tried to add above script but it still not working.
Hi there. I’m looking for a way to load my gravity forms via ajax to prevent autopopulated fields from beeing cached.
How can I use your plugin to load every form via ajax on page load and not only when somebody clicks the button?
This is so helpful, I have been trying to figure out how to put Gravity Form behind a button like this for a while.
I do have a question. When activating the button with a screen reader active, focus is not placed in the form area. How can I ensure that after the button click that focus is set to either the beginning of the form, or to the first input field?
Right now, focus is moved to the top of the post or page.
Thank. Very help. Holiday greetings.
wow cool, works, how can you get that way, what the tips?
hopefully you can give help again if there is a bug in some condition
Hello, thank you for sharing this great script. I have it working on my site but the input mask for the phone number isnt working. Any thoughts? Thanks again!
OK, so I solved it by doing the following, just seems like a dirty trick. If you or anyone else has a better idea (i’m sure it’s out there), please let me know.
$(“.ginput_container_phone”).each(function(){
let input = $(this).find(“input”);
input.mask( ‘(999) 999-9999’);
})
Hello,
Great example !!
I need to pass field value to the form through the button (i have now multiple buttons on the page with each a different value for a field), someone know how to do this ?
Thank you,
Nicolas
You are the man.
YOU
ARE
THE MAN
sincerely: thank you sir
Forms that are injected into the page after it has loaded no longer function correctly in Gravity Forms 2.5. The form will submit, but validation errors are not displayed to the user, nor is the confirmation message, and some callbacks fail to trigger. That is because gforms now wraps its form JS logic inside a DOMContentLoaded callback, which won’t run since the DOM has already loaded. Previously they used a jQuery ready() callback, which will run regardless.
The only solution I could think of was a find & replace to restore the old ready() callback. This solution is brittle since the search string could change in future gform versions:
response = response.replace(‘document.addEventListener( \’DOMContentLoaded\’, function($){‘, ‘jQuery(document).ready(function($){‘);
Thanks for the workaround Jonathan. I’ve updated the code to support Gravity Forms 2.5.
I’m having trouble with the following tag working when using your plugin:
{embed_post:post_title}
Any ideas?