Question

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:

  1. actionIndex() is called, it renders the index.php (the index.php contains the JS codes the design, but not the CGridView, where the webapp views the results)
  2. index.php rendert the _ajaxIndex.php files content.
  3. The JS code calculate the next 10 result, which will have to view on the webpage.
  4. actionAjaxIndex() is called. This give therefresh content of _ajaxIndex.php repeat from the 3. again.
  5. The JS code calculate again the next 10 resut...

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 :/.

Was it helpful?

Solution

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).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top