Cgridview Not Showing Second Page

I am trying to create custom search for model, after performing the search i show it CGridView

The first page is fine. there is pager at the bottom, but when i click on pager to move to second (or last page) the grid shows empty result, but there are enoungh records to show in second page.

my action looks like this




    public function actionSearch() {

        $this->layout = '//layouts/column1';

        $model = new SearchForm();

        $model->unsetAttributes();

        $result = NULL;

        if (isset($_POST['SearchForm'])) {

            $model->attributes = $_POST['SearchForm'];

            if ($model->validate()) {

                $r = new Document('search');

                

                $result = $r->publicSearch($model);

            }

        }

        $this->render('search', array('model' => $model, 'result' => $result));

    }



where searchform is custom model for colecting user input

my document model has public search method like this




    public function publicSearch(SearchForm $input) {

        // Warning: Please modify the following code to remove attributes that

        // should not be searched.


        $criteria = new CDbCriteria;

        $criteria->select = array('code', 'id', 'issue_date');

        $criteria->with = array(

            'customer' => array(

                'select' => 'name',

            ),

            'supplier' => array(

                'select' => 'name',

            ),

            'submitter' => array(

                'select' => 'name',

            ),

        );

        $criteria->together = true;

        $criteria->distinct = true;

        $criteria->order = 't.id ASC';

        $criteria->compare('t.code', $input->documentNumber, true);

        $criteria->compare('customer.name', $input->name, true);

        $criteria->compare('supplier.name', $input->name, true);

        $criteria->compare('submitter.name', $input->name, true);

        return new CActiveDataProvider($this, array(

                    'criteria' => $criteria, 

//                    'pagination' => array(

//                        'pageSize' => 5,

//                    )


                ));

    }

and my search view has cgridview like this




            <?php

            $this->widget('zii.widgets.grid.CGridView', array(

                'id' => 'document-grid',

                'showTableOnEmpty' => false,

//                'enablePagination' => false,

                'dataProvider' => $result,

                'summaryText' => '',

                'columns' => array(

//                    'code', 

                    array(

                        'class'=>'CLinkColumn',

                        'labelExpression'=>'$data->code',

                        'urlExpression'=>'Yii::app()->createUrl("document/view",array("id"=>$data->id))',

                        'header'=>'Code'

                    ),

                    'issue_date',

                    'customer.name',

                    'supplier.name',

                    'submitter.name',                    

                ),

            ));

            ?>



What am i missing?

Dear Friend

Kindly check whether the following removes the problem.




public function actionSearch() 

{

        $this->layout = '//layouts/column1';

        $model = new SearchForm();

        $model->unsetAttributes();

        if (isset($_POST['SearchForm'])) 

        {

            $model->attributes = $_POST['SearchForm'];

            if ($model->validate()) 

            {

                $r = new Document('search'); 

                $result = $r->publicSearch($model);

                Yii::app()->user->setState('result',$result);//SAVE IT IN SESSION.

            }

        }

        if(Yii::app()->user->hasState('result')

                $result=Yii::app()->user->getState('result');//GET BACK FROM SESSION.

        $this->render('search', array('model' => $model, 'result' => $result));

}



The reason behind this change is due to the fact that when you are clicking next button in pager,

it becomes all new fresh request. In this request, $_POST[‘SearchForm’] becomes void.

That forces us to save the values of $_POST[‘SearchForm’] in session and reuse it.

Regards.

dear seenivasan

thank you for your answer, the solution works great (the one from code)

in explanation below you mention to save searchForm in session (example in code saves $result)

so I have further questions

if there is no user logged in and no session start how do these session variables behave when there are multiple simultaneous requests (or there is a hidden session start)?

I tried another thing, to save searchForm as statefulForm (via gedPageState and setPageState) what happends is that my search button is POST request, and YII_PAGE_STATE is sent, but next page request from grid is GET request YII_PAGE_STATE is not set.

How can i use POST in CGridView page request?

Again thanks for working solution.

Or i changed something or there is a bug with this solution, now i have that the second page is not empty but repeated first page

You need save SearchForm value to session not results. Try this:

public function actionSearch() {

&#036;this-&gt;layout = '//layouts/column1';


&#036;model = new SearchForm();


&#036;model-&gt;unsetAttributes();


&#036;result = NULL;


[b]if(Yii::app()-&gt;user-&gt;hasState('SearchForm')[/b]

$_POST[‘SearchForm’]=Yii::app()->user->getState(‘SearchForm’);//GET BACK FROM SESSION.

if (isset(&#036;_POST['SearchForm'])) {


	&#036;model-&gt;attributes = &#036;_POST['SearchForm'];


	if (&#036;model-&gt;validate()) {


		&#036;r = new Document('search');


		


		&#036;result = &#036;r-&gt;publicSearch(&#036;model);


		[b]Yii::app()-&gt;user-&gt;setState('SearchForm',&#036;_POST['SearchForm']);//SAVE IT IN SESSION.[/b]


	}


}


&#036;this-&gt;render('search', array('model' =&gt; &#036;model, 'result' =&gt; &#036;result));

}

Dear Friend

If i am not wrong ,the following is my conviction.Every session is unique one that is shared by client browser and server.Even guest(anonymous) user has a session.Variable set in one session of a user is not going to interfere with other user’s session.

You can also do something like this.




Yii::app()->session->add('result',$result);

Yii::app()->session->get('result');



If you have problems, kindly try the following.

In your publicSearch method remove the following line.




$criteria->order = 't.id ASC';



Regards.

I am having the same problem.

Controller:




if(isset($_POST['continent']))

{

    $constraint['continent'] = $_POST['continent'];                        

    if(isset($_POST['country']))   $constraint['country'] = $_POST['country'];

    $data = DAO::queryMako($constraint);                        

    $dataProvider = new CArrayDataProvider($data, array('keyField'=>false,

                     'sort'=>array(                                

                     'attributes'=>array(                                        

                          'REGIONID',                                

                      ),),                       

                     'pagination'=>array(                         

                                'pageSize'=>2,                 

                     ),));                

     Yii::app()->user->setState('dp',$dataProvider);                

}                

if(Yii::app()->user->hasState('dp'))                       

    $dataProvider=Yii::app()->user->getState('dp');                

$this->render('display_mako',array('dataProvider'=>$dataProvider));

View:


<h1>Display Mako</h1>


<?php

if(isset($dataProvider)) {

$this->widget('zii.widgets.grid.CGridView', array(

    'dataProvider' => $dataProvider,

));

}

?>



The problem is its displaying the same contents on every page. But the total count is correct.

Can someone suggest what i am missing.

Regards,

Nivas

Hi,

I think this is the problem:

The CDataProvider have a private $_data variable, where the DataProvider is cache the filtered partial data - when you save the dataprovider to the session (setState()) this variable also saved, and on the second page when the widget call the getData() method the Yii is use this cached value:




public function getData($refresh=false)

{

        if($this->_data===null || $refresh)

                $this->_data=$this->fetchData(); // this line is skipped, because the $this->_data is not null and the $refresh is false

        return $this->_data;

}



because the $refresh variable is not parameterized in the widget - try to clear the $_data variable with the setData:




...

if(Yii::app()->user->hasState('dp')) {

    $dataProvider=Yii::app()->user->getState('dp');

    $dataProvider->setData(null); // or $dataProvider->data = null;

}



Hi Argent,

That really helped me and saved a lot of time.

Thank you so much.

Regards,

Nivas