Have a D7 multistep form with AJAX to replace divs, which takes the user through a 'wizard' and then I intend to redirect him to another part of the site.

Seems to be impossible to do after validation and on the final submit.

After hours I spent looking into this, apparently AJAX in D7 sets $form_state['no_redirect'] to TRUE so no redirects can ever occur with $form_state['redirect'] = $url.
(drupal_goto($url) etc... simply results in 'AJAX 200' errors as well)

So whats the big thing I am missing here ?

How do you redirect a user once you have finished your multistep form?

Comments

sbanerjee.302’s picture

You can set the redirection code after the form submit handler has processed the form values successfully. That should work.

trampjuice’s picture

$form['Next'] = array(
'#type' => 'button',
'#attributes' => array('onClick' => 'location.replace("cart"); return false;'),
'#value' => t('Next'),
);

The only way I have done this, is by setting up another ajax callback (which replaces stuff in div wrappers) so a client side button is returned which will redirect them away from the multistep ajax form to a shopping cart url or whatever on the final step.

You cannot redirect from a ajax form via normal means because $form['no_redirect'] is set to TRUE by design by the ajax form processing code, and is not set to FALSE at a later stage (successful submission).

D7 drupal_form_redirect() docs
---------------------------------- ...
"If $form_state['no_redirect'] is TRUE, then the callback that originally built the form explicitly disallows any redirection, regardless of the redirection value in $form_state['redirect']. For example, ajax_get_form() defines $form_state['no_redirect'] when building a form in an Ajax callback to prevent any redirection. $form_state['no_redirect'] should NOT be altered by form builder functions or form validation/submit handlers. "

trampjuice’s picture

Finally got this working after knocking up a test module. I could not work out why I had so many problems trying to get redirection working from the last step of a multistep ajax form but others seemed not to be bothered by this. I could not move to a menu hook and present the user another form whatever I did. Multistep forms usually turn out to be huge blocks of code, with many callbacks so they are difficult to debug for weird errors like this.

So I knocked up a test module and started to incorporate a few fieldsets etc.. In my much simpler 2 page test ajax multi step form I could easily redirect and embed buttons whatever I did with callbacks. Worked fine. So something within all my main forms steps was preventing redirection.

I still don't know what it could be as its normal FAPI code bar a few ajax bits. Anyway - After seeing how a multistep ajax form should work from my knocked up test module, I experimented and found a workaround for any other people who are in this situation.

To cure the problem I set the form['#action'] = my submit url right at the start of the form(). If I did it in the last step it wouldn't work which seems a bit bizarre. From looking at the HTML the form submitted to itself in html code if I didn't add this, and when I added the action statement at the start - it still worked ok, but there was no self-submit hardwired into the html.

Anonymous’s picture

How did you get this to work?

I have a single textfield with a custom autocomplete on it. I want the form to submit and redirect to the node URL that is chosen through the autocomplete.

So far everything functions great up until the ajax submit. With drupal_goto in the submit handler, it errors out. With $form_state['redirect'] nothing fires.

Do I need to write my own javascript function? I'm afraid any of my js calls will override the autocomplete javascript.

Any help is appreciated.

Thanks!

trampjuice’s picture

I have been keen to get to the bottom of this - it has caused me no end of grief and wasted a lot of my time resulting in a hacked workaround based on form action.

I STILL think what the hell was that about - I CAN'T DO A F***ING SIMPLE REDIRECT IN DRUPAL 7 WITH AJAX!!!. I have now finished the project, but this continues to undermine my confidence in developing on Drupal 7.

If you post your code here I will have a look over it and try and get it working.

I will single step through it with a debugger if needs be to find the answer.

An autocomplete box and redirect - sounds like a great test case of this curious error as well!

gambaweb’s picture

the solution is to use ctools ajax redirect command
http://api.drupal.org/api/drupal/includes--ajax.inc/group/ajax#comment-2...
you have to add
ctools_include('ajax');
ctools_add_js('ajax-responder');
to you callback function
take a look at ctools_ajax_sample_login_success function in ctools_ajax_sample.module

babusaheb.vikas’s picture

Hi,

For redirection in drupal if using Ajax, you will have to put following code.

ctools_include('ajax');
ctools_add_js('ajax-responder');
$commands[] = ctools_ajax_command_redirect('node/1');
print ajax_render($commands);
exit;

If you put the above code to your submit ajax handler , then it will redirect to certain url you provided in ajax command redirect.

Vikas kumar

Rene Hostettler’s picture

This worked for me

N20’s picture

This works for me too, thanks for sharing.

tce’s picture

This worked for me but had to use drupal_exit() instead of exit() as I was also using the ctools object caching.

mahimajulka’s picture

This works like charm. Thanks a lot ..

Shashwat Purav’s picture

Also if you want to send parameters to the redirected page.

<?php
ctools_ajax_command_redirect('your_url_path', 0, array('query' => array('param1' => 'value1')));
?>

Thank You,
Shashwat Purav

shobhit_juyal’s picture

However, if you can explain the reason then it will be very helpful.

I was using the [ return array('#type' => 'ajax', '#commands' => $commands); ]
before and it was not working. But when I replaced that line with the below:
[
print ajax_render($commands);
exit;
]
then the magic worked for me. But I am still curious to know the difference.

Thanks

sam.spinoy@gmail.com’s picture

Another solution would be to use the Rules module. Lots of forms show up in the Event list, so you can select them and add a redirect as Action.
May be a bit of a "heavy" solution but I had the module installed for other purposes anyway.

sydneyshan’s picture

I know this is an old thread, but Google is still displaying it near the top of searches for Drupal 7 AJAX redirect so I thought I'd add my solution.

I added a Drupal.behaviors object via javascript (of which the 'attach' function I believe is automatically fired upon page load, and *before* an ajax form submission):

(function ($) {
  Drupal.behaviors.my_redirect = {
    attach: function() {
      
      $("form#form_id_here select#select_id_here").change(function(e){
        e.stopPropagation();
        //redirect the user to the node ID referenced in the chosen select list option (before the AJAX form is submitted!):
        window.location.pathname = '/node/' + $("option:selected", this).val();
      });
      
    }
  };

}(jQuery));
chrisnovak’s picture

I had this same issue and found the $form_state['no_redirect'] was set to true just like trampjuice pointed out. This makes sense since the page is not being rebuilt by the server, the AJAX is only replacing sections of a full page.

I solved this by following the Drupal examples project. Check out the ajax_example_wizard() in ajax_example_graceful_degradation.inc, and see that the last submit is not AJAX:

if ($step == 3) {
    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t("Submit your information"),
    );
  }
  if ($step < 3) {
    $form['next'] = array(
      '#type' => 'submit',
      '#value' => t('Next step'),
      '#ajax' => array(
        'wrapper' => 'wizard-form-wrapper',
        'callback' => 'ajax_example_wizard_callback',
      ),
    );
  }

Do not add the '#ajax' attribute to any submit you want to do a redirection on.

Jaypan’s picture

You can redirect a user in an AJAX submitted form by doing the following:
1) Ajaxify your button
2) In your Ajax callback, create a custom 'redirect' command
3) In an external javascript file, redirect the user based on the command

Basic example:

/**
 * Form definition
 */
function mymodule_some_form($form, &$form_state)
{
  // 1) Create an ajaxified button
  $form['submit_button'] = array
  (
    '#type' => 'submit',
    '#value' => t('Redirect user'),
    '#prefix' => '<div id="some_form_wrapper">',
    '#suffix' => '</div>',
    '#ajax' => array
    (
      'wrapper' => 'some_form_wrapper',
      'callback' => 'mymodule_some_form_ajax_callback',
    ),
  );

  // 2) Add a javascript file (code to be shown further down)
  $form['#attached']['js'][] = array
  (
    'type' => 'file',
    'data' => drupal_get_path('module', 'mymodule') . '/js/some_form.js',
  );

  return $form;
}

// Note: submit function not shown as it's not relevant to this example.

/**
 * Ajax callback function
 */
function mymodule_some_form_ajax_callback($form, &$form_state)
{
  $commands = array();
  $commands[] = array
  (
    // Note: we will use this command in the .js file
    'command' => 'redirectUser',
    // The path the user is directed to is given here
    'path' => 'path/to/some/page',
  );

  return array('#type' => 'ajax', '#commands' => $commands);
}

Finally, some_form.js. We add our own custom Ajax command, redirectUser()

(function(Drupal)
{
  Drupal.ajax.prototype.commands.redirectUser = function(ajax, response)
  {
    // response.path is the path we gave in our Ajax callback
    window.location.reload(response.path);
  };
}(Drupal));
tkuldeep17’s picture

Thanks Jaypan for sharing.. Worked for me... :-)

tkuldeep

Marko B’s picture

There is no need to do custom JS function you can use ctools_ajax_command_redirect('');

like I described here

https://drupal.org/comment/8586091#comment-8586091

Jaypan’s picture

That's fine if you are using the ctools module, but if you aren't, the above method will work.

esod’s picture

Thanks @jaypan for your very helpful code. The only change I needed to make was in mymodule_some_form_ajax_callback():

/**
 * Ajax callback function
 */
function mymodule_some_form_ajax_callback($form, &$form_state) {
  $commands = array();
  $commands[] = array(
    // Note: we will use this command in the .js file
    'command' => 'redirectUser',
    // The path the user is directed to is given here
    'path' => 'user',
  );
  if ($errors = form_get_errors()) {
    return $form;
  } else {
    return array('#type' => 'ajax', '#commands' => $commands);
  }
}

Without form_get_errors(), the form is being submitted, but the redirect does not happen. In my case I'm using the user_login form.

johnhanley’s picture

Thanks for this post. Very helpful--thanks.

Note window.location.reload(response.path); didn't work for me, but window.location.replace(response.path); works like a charm.

sivaguru_drupal’s picture

Thanks to Jaypan, esod & johnhanley. Ajax applies perfectly on my add to cart form.

zarabzaa’s picture

Thanks for all the suggested solutions that could help me to - no luck though. I have a similar problem that can't figure out a solution for, despite trying all responses here.

So, I have a form with two elements an option and a textfield. These are built-in with the form. In an ajax callback function, using Ajax commands, I add two other fields another textfield and a textarea.

So far, the form runs and rebuilds perfectly fine. But only visually. When I try to read the values typed in or stored-from-beginning, nothing happens except that only the values for the first two fields that were originally built-in with the form are displayed.

I think the problem is either 1) I am not rebuilding/rendering the form properly, or 2) I am not calling the elements/fields properly.

Thanks

5418ryadav’s picture

This below snippet is working good for me

$path = "user";
ctools_include('ajax');
ctools_add_js('ajax-responder');
$commands[] = ctools_ajax_command_redirect($path);
print ajax_render($commands);
exit;