You are viewing revision #9 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version.
In this How-To I'll show you:
1.) A reliable alternative to Yii::app()->request->isAjaxRequest (because it doesn't work for everybody and it's not reliable)
2.) How to add extra data to a form without setting a hiddenField, only using javascript, before sending the form.
Here you can read more about why 'isAjaxRequest' isn't reliable: http://www.yiiframework.com/forum/index.php?/topic/4945-yiiapp-request-isajaxrequest/
The main idea is adding a parameter to our request which tells us if the current request is an ajax-request or not. So if you work with an ajax form, you would for example add a hiddenField named 'isAjaxRequest' and set the value to '1'. But this won't work, if you have a form which can be sent with both, ajax- and usual post-request for users having disabled javascript. So the solution is adding a parameter 'isAjaxRequest' to our form with javascript, before sending it, instead of adding a hiddenField.
After building our form, we add a submitButton like this (in this case for searching users):
<?php
// Sorry for bad shifting, it's not my fault ...
echo CHtml::ajaxSubmitButton('Search', CHtml::normalizeUrl(array('user/search')),
array(
'data'=>'js:jQuery(this).parents("form").serialize()+"&isAjaxRequest=1"',
'success'=>
'function(data){
$("#searchResult").html(data);
$("#searchResult").show();
return false;
}'
),
array(
'id'=>'ajaxSubmit',
'name'=>'ajaxSubmit'
));
?>
jQuery(this).parents("form").serialize() is what Yii's ajaxSubmitButton would usually do, if you had not set the 'data' parameter. Now we add +"&isAjaxRequest=1" to set a parameter 'isAjaxRequest' with value '1' to our ajax-request. So this is how to add parameters to ajax-request with javascript. You can add as many parameters as you want like this. js:jQuery(this).parents("form").serialize()+"&isAjaxRequest=1¶meter1=value1¶meter2=value2"
By setting the parameter 'isAjaxRequest' we can filter our ajax request in our controller-action like follows:
public function actionSearch() {
if($_POST['isAjaxRequest']=='1') {
// your business logic for ajax-request
// usually with renderPartial at the end, in order to render a partial view
$this->renderPartial('ajaxSearchResult', array('param1'=>'value1'), false, true);
}
else {
// your business logic for non-ajax-request
// usually with render at the end, in order to render a whole view with your layout
$this->render('searchResult',array(
'param1'=>'value1',
));
}
}
Very simple, but works ...
Really usefull
Very simple, beautiful and usefull.
I prefer to use links, could I use ajaxLink that way? (I have tested it and works fine)
echo CHtml::ajaxLink('Search', CHtml::normalizeUrl(array('user/search')), array( 'type'=>'POST', 'data'=>'js:jQuery(this).parents("form").serialize()+"&isAjaxRequest=1"', 'success'=> 'function(data){ $("#searchResult").html(data); $("#searchResult").show(); return false; }' ), array( 'id'=>'ajaxSubmit', 'name'=>'ajaxSubmit' ));
Thank you.
Alternative
One thing to note is that Yii internally uses
getIsAjaxRequest
for some things, likeCWebUser
'sloginRequired
method. So IMHO it is a good idea to makegetIsAjaxRequest
work with the GET-parameter-method mentioned above. So you can still usegetIsAjaxRequest
in your own code.I created a behavior that checks on each request if the
isAjaxRequest
-GET-parameter is set. If so, theHTTP_X_REQUESTED_WITH
header will be set manually (if not already done). SogetIsAjaxRequest
will work like expected. Place this file in yourcomponent
folder:/** * Class AjaxRequestBehavior * * Yii's CHttpRequest->getIsAjaxRequest method uses only the HTTP_X_REQUESTED_WITH header * to check if the request was made using Ajax. But this header may be removed by some * Webservers or proxy-servers. So one should always include a GET-parameter 'isAjaxRequest' for Ajax- * requests to indicate that the request was made using Ajax. * * This Behavior checks whether the GET-parameter exists and if so it sets the * HTTP_X_REQUESTED_WITH header manually. Thus the getIsAjaxRequest method will be more * reliable and internal Yii functions will benefit from this, for example CWebUser->loginRequired. */ class AjaxRequestBehavior extends CBehavior { public function attach($owner) { $owner->attachEventHandler('onBeginRequest', array($this, 'ensureXHRHeaderIfAjaxRequest')); } public function ensureXHRHeaderIfAjaxRequest($event) { if (isset($_GET['isAjaxRequest']) && (!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || $_SERVER['HTTP_X_REQUESTED_WITH']!=='XMLHttpRequest')) { $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; } } }
Then simply add this behavior to your Application using the
config/main.php
:... 'behaviors' => array( 'application.components.AjaxRequestBehavior' ), ...
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.