I need a help in refactoring, or in design :). I did my webapp, it works well. But I still can't understand well the Ajax process in the Yii. For example, when I use the $.fn.yiiGridView.update()
method, I saw this return by the all webpage and not just with the content of CGridView
. It was interesting for me.
But now: at the index view, I use a CGridView
, but without pager! This is a simple bet game webapp. And at the index.php I view only 10 bet/result on the page, and after 10 seconds I view the next 10 bet/result and again the next 10 result/bet after 10 seconds :), with JavaScript.
The simple process like this:
Notice: While the admins insert the results at the admin webpage, the webapp has to show the temporary results. This is why I need to refresh the summary and the round JS variables in the _ajaxIndex.php
Controller
/**
* Lists all models.
*/
public function actionIndex() {
Yii::app()->language='hu';
$model = new Result('search');
$model->unsetAttributes();
if (isset($_GET['Result']))
$model->attributes = $_GET['Result'];
if (isset($_POST['offset']) && $_POST['offset'] >= 0)
$model->offset = $_POST['offset'];
$summary = Result::getCountSavedResults();
$model->isLimited = true;
$this->layout='projector';
$this->render('index', array('model' => $model, 'summary'=>$summary));
//$this->actionAjaxIndex();
}
/**
* List all models by Ajax request.
*/
public function actionAjaxIndex() {
Yii::app()->language='hu';
$model = new Result('search');
$model->unsetAttributes(); // clear any default values
if (isset($_GET['Result']))
$model->attributes = $_GET['Result'];
if (isset($_POST['offset']) && $_POST['offset'] >= 0)
$model->offset = $_POST['offset'];
$summary = Result::getCountSavedResults();
$model->isLimited = true;
$this->renderPartial('_ajaxIndex', array('model' => $model, 'summary'=>$summary));
}
I would like to terminate this code repeat in the actionIndex(). But I don't have any idea how I can do... I tried to call actionAjaxIndex etc. But before I can call the actionAjaxIndex I got PHP errors from Yii. (Summary variable is not exist, etc.)
View - Index.php
<!--<h1><?php echo Yii::t('strings','Results'); ?></h1>-->
<?php
echo CHtml::image(Yii::app()->request->baseUrl.'/images/toplista.jpg', "Fogadás");
?>
<script type="text/javascript">
// Initialize the variables for calculating
var summary = <?php echo $summary ?>; // get all stored results
var timeout = 10 * 1000; // in Milliseconds -> multiply with 1000 to use seconds
var current = 0;
var turn = 0;
var rounds = Math.floor(summary / 10);
</script>
<?php $this->renderPartial('_ajaxIndex', array('model'=>$model, 'summary'=>$summary)); ?>
<script type="text/javascript">
// Refresh the CGridView's content in _ajaxIndex.php
window.setInterval("refresh()", timeout);
// Get the offset to the search() to set the criteria
// Increase turn.
function counter(){
turn += 1;
if(turn > rounds){
turn = 0;
}
return turn *10;
}
function refresh() {
<?php
echo CHtml::ajax(array(
'url'=> CController::createUrl("result/ajaxIndex"),
'type'=>'post',
'data'=> array('offset'=>'js: counter()'),
'replace'=> '#ajax-result-grid',
))
?>
}
</script>
View - _ajaxIndex.php
<?php
/* @var $model Result */
?>
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'ajax-result-grid',
'dataProvider'=>$model->search(),
'columns'=>array(
array(
'header'=>Yii::t('strings','No.'),
'value'=> $model->offset.' + $row+1',
'htmlOptions'=>array('style'=>'width:50px;'),
),
array(
'header'=>Yii::t('strings','team_name'),
'name'=>'team_id',
'value'=>'$data->team->name'
),
array(
'header'=>Yii::t('strings','value'),
'name'=>'value',
'value'=>'$data->value'
),
),
)); ?>
<script type="text/javascript">
// This is need while the admins insert the results during this page is run.
summary = <?php echo $summary ?>;
rounds = Math.floor(summary / 10);
</script>
Yes, I think I don't understand clearly the Ajax process in the Yii :/.
Actually you've already made a huge step forward, using the same template - _ajaxIndex.php
- both for AJAX calls and for the initial page load. But yes, you can go even further in that direction - by using a single action as well.
In this action should be a check for how exactly the method is called, via AJAX or not. Depending on the results, you either render the full page - or just a partial.
Usually this check is done as simple as...
if (Yii::app()->request->isAjaxRequest) { ... }
But there's a problem here: this check depends on the custom HTTP Header HTTP_X_REQUESTED_WITH
, used by many JS libraries implementing their own AJAX routines. Sadly, some proxy servers drop this header, so it might be unreliable. To be 100% sure, just supply another param in your AJAX helper (the easiest is ajax
), then check this param (too).