redirect not working when called via Ajax-Request

Hi,

I got the following code in my App:




			if(Yii::app()->request->isAjaxRequest)

				$this->redirect( array('order/xxx'));

			else

				$this->redirect( array('order/yyy'));



When the “isAjaxRequest” is true the redirect doesn’t happen.

It is recived by the browser, however it is not renderd.

What is wrong?

Thx Andreas

I don’t know, if you actually can use redirects within an AJAX calls?

Redirect is done on server side, but for full application (browser) request while AJAX calls are most time initiated for updating small parts of application, by JavaScript.

I’m not specialist here, but to be honest I’ve never seen AJAX calls using redirects and would be a little bit surprised, if that would be possible.

AFAIK You need to do some custom response and hook on to that with Javascript to make this work.

Following the logic:




if(Yii::app()->request->isAjaxRequest)

                                $this->redirect( array('order/xxx'));

                        else

                                $this->redirect( array('order/yyy'));



It means you are calling the action in a different request and the redirect will happen in that request NOT in the initial request that triggered your ajax call. Makes sense this way ?

You should do something like:




if(ajax request){

   echo json_encode(array('redirect'=>$this->createUrl('/order/xxx')));

}



Then, using javascript, parse the json response and simple do a :

window.location.href=jsonParsedObject.redirect;

This seems to be a very interesting approach. Thanks (+1) twisted1919!

I think I wouldn’t get myself to such solution, although I think I know AJAX and jQuery a little bit! :]

Always good to have here people bringing new, bright ideas! :]

The thing is that i had same problem/question while ago and this is the way to go.

In my apps, i do all form submissions via ajax, it is way better for the app itself (less processing) and for the client because while the app is doing the processing i can show a nice message to client letting him know the application is doing some work and he needs to wait (also i lock the form to prevent double submissions)

You can take a look at the MessageStack extension, this is one of the reasons i created it, it simplifies my workflow very much, basically in my controller i have something like:




if(Yii::app()->input->post('Product'))

{

	$this->performAjaxValidation($product);

	$msg = $product->saveModel(Yii::app()->input->post());


	if(Yii::app()->request->isAjaxRequest)

		$msg->toJson();

}



And the saveModel model method does something like:




public function saveModel(array $data)

{

	$msg=Yii::app()->messageStack->reset()->setIsError()->set('action', $this->isNewRecord ? 'create':'update');


	$productData=$data['Product'];

	$connection=Yii::app()->getDb();

	$transaction=$connection->beginTransaction();


	try

	{

		$this->attributes = $productData;

		$isNewRecord = $this->isNewRecord;

		if(!$this->save())

		{

			throw new Exception(CHtml::errorSummary($this));

		}

		$transaction->commit();

	}

	catch(Exception $e)

	{

		$transaction->rollBack();

		return $msg->set('msg', $e->getMessage());

	}

	return $msg->setIsSuccess()->set('redirect', Yii::app()->createUrl('product'));

}



As you see from my model i return the messageStack object itself, which will call toJson() in the controller which will cause the application to end and print all the stored data in a json format.

Having in mind the request has been made via ajax, this response can now be read in the callback of the ajax call and we can use returned variables as we want.(ie window.location.href=object.redirect or show the obj.msg to the client, because this contains an error message which needs to be seen)

Anyway, there are other ways to do all this stuff, but this is mine and it works perfectly :)

Here you’re touching widely discussed problem, what if user of your web app has JavaScript disabled?

Although I generally agree with you, I must point you out, how it was solved for example with CGridView. Test any application containing it with and without JavaScript. You’ll notice that it works in both situations, self adapting to browsers with Ajax / JavaScript disabled, by switching to POST in that case.

Of course, you can have JavaScript enabled as prerequities to your application and simply tell your customer that you don’t support browsers without JavaScript. But that isn’t much professional. Don’t you agree?

I’m doing exactly the same im my app, without AJAX. I use a simple JavaScript function that displays jQuery UI dialog with a clock and some message and right after I’m doing GET redirection or POST form submission.

You also don’t need AJAX for that. You can disable form submit button in it’s onClick and this will happen as first phase, before form will be submited. Many banks does the thing this way.

THnxxxxxxxxxxxxxxxxxxx…it helped me…great idea…!!!

Just so people know exactly how to do what he suggest above:

in your controller action you would do the following:





if(Yii::app()->request->isAjaxRequest) {

					

   $redirection = CJSON::encode(array('redirect'=>$this->createUrl('/projects/cescreate',array('id'=>0,'wiz_id'=>$model->id))));

   echo '['.$redirection.']';

					}



In my case I am posting to the actionCreate() function in my controller using the following jquery:

After the post I am parsing through the json and returning the redirect url


 

var data = { "UsersWizardNames": {

                                  "user_id" : '1',

		                  "wizard_name_id" : '1',

		                  "description" : 'bonjour'

                                 } 

           }


$.post("http://hq-dev-01/ceswebapp/index.php?r=usersWizardNames/create",data)

 .done(function(results){													             

                         var myData = JSON.parse(results);

			 $.each(myData, function () {

                                console.log(this.redirect);							   

                                 window.location=this.redirect

			 });

												

													

  });




Hope this helps someone.

Personally I need to either work it out, or good examples to help me get it.

I do easier.

Just replace

$this->redirect( array(‘order/xxx’));

on

echo ‘<script type=“text/javascript”>window.location.href="/order/xxx"; </script>’;

Works for me. But do not pretend to be an ideal solution)