1

I'm using FAPI #ajax to make the form more user friendly (it reloads in-place on validation). Works like a charm. However I would like to reload the page after form is submitted. How to that?

Obviously if I call for example drupal_goto(current_path()) inside submit handler it won't do anything since this function is called via AJAX call. The actual page that user is on is not reloaded.

Is there some neat Drupal AJAX API trick that will allow whole page reload after AJAX form submit?

  • 2
    If you want to reload anyway, why to bother with AJAX? – Mołot Apr 4 '14 at 9:22
  • 2
    Validation reloads page too. I want to reload only after successful submit. Not on every submit. – SiliconMind Apr 4 '14 at 9:25
0

If you want to avoid the ctools dependency but want to avoid the pitfalls of inline js-ing...

In your submit handler

if (current_path() == 'system/ajax') {
  // This was an ajax submission.

  // Cause Drupal to rebuild the form
  $form_state['rebuild'] = TRUE;
  // Special flag, call it what you want.
  $form_state['ready_to_go'] = TRUE;
}

Then in your build form function do something like

if (!empty($form_state['ready_to_go'])) {

  // Add js to autosubmit, stored in an external js file.
  $form['#attached']['js'][] = drupal_get_path('module', 'mymod') 
    . '/my-bit-of-js.js';

}

Then your my-bit-of-js.js file finds the form and submits it immediately.

What this will do

Your form is ajax enabled. Validation errors are returned, as you wish. Once there are no validation errors, the form is submitted, but is actually returned rebuilt identical, except for the inclusion of your auto-submit-my-form js, which submits the form through a non-ajax submission, and from there you can issue whatever redirect you want.

While you could have your js do the redirect (as in your inline example), the benefit of doing the full non-ajax submission is that you can use PHP to determine where to redirect to, since the external js file is not going to be based on any of your form values, which the redirect might need to be. I know in this specific case you just want to reload. So just treat all this as a helpfully intended jus' sayin' :-)

Aside: Multi-step form ajax except last page

I came upon this when I had a multi-page form that I wanted to be ajax until the final page (because I wanted a redirect on final submission). The way I'd done this was that I'd built the last page of the form without the #ajax on the submit elements. This resulted in quirky behaviour though because Drupal could no longer call the ajax callback that would return the last page of the form because it looks to the rebuilt form to find the callback(!). The solution I found was to hide ('#type' => 'hidden') the "next" button and leave it's #ajax stuff in place, but then provide a different submit button without the #ajax stuff (which needed a different #name).

10

For the purpose of the question, an easy-ish way to do a redirect after ajax is with ctools and ctools_ajax_command_redirect

// In your ajax form submit callback
ctools_include('ajax');
ctools_add_js('ajax-responder');
// Path to redirect to
$path = 'node/12';
$commands[] = ctools_ajax_command_redirect($path);
// you can also use ctools_ajax_command_reload() –  xurshid29
print ajax_render($commands);
drupal_exit();

Note, it depends on ctools, which is a popular contrib module.

3

Another simple solution could be using a custom ajax command in your module JS file :

(function($) {
    // Custom AJAX commands
    if(typeof Drupal.ajax != "undefined") { // Ensure follwing code will not generate errors in administration pages
        Drupal.ajax.prototype.commands.reloadPage = function(ajax, rsp, status) {
            location.reload();
        };
    }
})(jQuery);

Then call it when returning your array of commands in your ajax callback function :

$commands = array();
...
$commands[] = array('command' => 'reloadPage');
...
return array('#type' => 'ajax', '#commands' => $commands);
-2

Instead of messing with ctools i've just set a flag in submit handler to let the ajax callback know that the form was submitted correctly and the page can be reloaded. Then inside the callback function I just returned some JavaScript instead of a form.

function my_module_ajax_callback($form, $form_state) {
  if ($form_state['my_flag']) {
    $ret =  '<script>';
    $ret .= 'jQuery(document).ready(function($) {';
    $ret .= '  location.reload(true);';
    $ret .= '});';
    $ret .= '</script>';
  }
  return $form;
}

Works perfectly.

  • Whilst this may work you are injecting inline javascript into the DOM. It is generally thought of as bad practise because it will be hard to modify later. If you must inject javascript I would suggest you use the #attached key in the form item. – kevin.coyle Sep 4 '14 at 14:56
  • Yes I know. I don't like this solution either, but it works. In this particular case it made much more sense that adding ctools dependency just for such a small thing. – SiliconMind Sep 4 '14 at 18:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.