[SOLVED] Pagination in CGridview

Dear All,

In standard Yii CRUD result, we will have the admin page already paginating. My concern is, for example we are on page 5, then view one of the record, then I have a redirect link to the admin page, if I click on this link, it will bring me back to admin page with page 1. How could I go to page 5?

Thanks in advance for your help.

Regards,

Daniel

Hi Daniel,

In my case, and to solve that issue, I will overwrite the back to admin link and include the page it was and for that, you will also have to get the value of the page CGridView was. That means, you’ll also have to include your edit buttons with the value of page parameter (normally is: Modelname_page).

I have successfully done that for my specific CMS that has nothing to do with the one that comes by default with Yii. And I created my own grid and pagination widgets. I guess that you dont want that.

Hi Antonio Ramirez,

Could you explain more that? It’s a very important topic. I think many persons need that stuff.

Thanks!

I wrote a small wiki about that

http://www.yiiframework.com/wiki/122/quick-tip-about-pagination-params/

I will write another one that actually explains how to maintain the same page using CGridView

Here is also a good tuto with CButtonColumns… maybe you can tweak it and include the current page on their edit, update, delete buttons

http://www.yiiframework.com/wiki/106/using-cbuttoncolumn-to-customize-buttons-in-cgridview/

I did it differently though

Dear Antonio,

Thank you for the example. I will find some time to study that.

Cheers,

Daniel

Hi Daniel,

A promise is a promise. Here a way to do what you are looking for:

http://www.ramirezcobos.com/2010/12/19/how-to-maintain-pages-on-cgridview/

If you find it useful, I will post it as a WIKI in this site.

Hope it helps you man.

Hi Antonio,

This is very helpful. But, one thing that I need to mention after studying your code, this is only work if in the CGridView I set the "ajaxUpdate"=>false. Otherwise, I cannot get the Modelname_page parameter.

Another question, how can I get the parameter if I use ajax in the CGridView?

Thanks a lot Antonio, you are the best! One of the most helpful person in yii’s forum.

Hi Daniel,

It is weird as when doing any calls it gets the value from the HREF property of the links (remember than on the first page you wont see the parameter as a page is not set, the parameter starts from page 1, that is second page)

The only one who does an ajax call by default and is ‘monitored’ by CGridView Javascript functions is the delete. Check the following code:




// code extracted from init() function

// it does show that if no click event 

// is placed, the link will fire by default

// as it should be, therefore the solution 

// provided in the blog is correct 

foreach($this->buttons as $id=>$button)

{

	if(strpos($this->template,'{'.$id.'}')===false)

	     unset($this->buttons[$id]);

	else if(isset($button['click'])) // see how it looks for the click event?

	{

	   if(!isset($button['options']['class']))

	          $this->buttons[$id]['options']['class']=$id;

	  if(strpos($button['click'],'js:')!==0)

		$this->buttons[$id]['click']='js:'.$button['click'];

	}

}

//-------------------------------

// code extracted from initDefaultButtons


// check this code here, see that is the delete

// function the only one monitored by CGridView?

$this->buttons['delete']['click']=<<<EOD

      function() {

	$confirmation

	$.fn.yiiGridView.update('{$this->grid->id}', {

		type:'POST',

		url:$(this).attr('href'),$csrf

		success:function() {

			$.fn.yiiGridView.update('{$this->grid->id}');

		}

	});

	return false;

}

EOD;


//---------------------------

// code extracted from the rendered Javascript

// look that is the delete the only one 'live' monitored

jQuery('#news-grid a.delete').live('click',function() {	

     if(!confirm('Are you sure you want to delete this item?')) return false;	

     ....



This is done this way as by default Yii, jumps to an edition and view Views of the Models.

Make sure you are on page number 2 to check for the parameter. It should be ok my friend. If not, drop the code in here and we will see how we can to the right answer.

Thank you very much for your kind words Daniel. There are lots of good people here ready to collaborate with others to get to the best solution that truly helped me through my learning experience, there are so many I cannot even name them all. Respect for all of them.

Hi Antonio,

Of course, I pay a lot of respect to yii community. I was just very happy that someone is really helping me and even pay a lot of attentions to make sure newbies like me can solve our problems.

Here is my code:




...

if( $page ){

    foreach(array('view','update','delete') as $id){

        $buttons[$id.'ButtonUrl'] = 'Yii::app()->controller->createUrl("'.$id.'",array("id"=>$data->primaryKey,"Account_page"=>'.$page.'));';

    }

}


...


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

            'id'=>'account-grid',

            'dataProvider'=>$dataProvider,

            'selectableRows' => 2,

            [color="#FFFF00"]'ajaxUpdate'=>false,[/color]

            'columns'=>array(

                    array(

                        'name'=>'AccountNo',

                        'type'=>'raw',

                        'value'=>'CHtml::link(CHtml::encode($data->AccountNo), array("view", "id"=>$data->ID, "page"=>$dataProvider->pagination->currentPage ))',

                        'htmlOptions'=>array('style'=>'text-align: center; width: 60px;'),

                    ),

                    'AccountName',

                    array(

                        'name'=>'Level',

                        'htmlOptions'=>array('style'=>'text-align: center; width: 50px;'),

                    ),

                    array(

                        'name'=>'NormalBalance',

                        'htmlOptions'=>array('style'=>'text-align: center; width: 50px;'),

                    ),

                    array(

                        'name'=>'Classification',

                        'type'=>'raw',

                        'value'=>'$data->Classification',

                        'htmlOptions'=>array('style'=>'text-align: left; width: 120px;'),

                    ),

                    $buttons,

            ),

        'pager'=>array('cssFile'=>false,

                       'header'=>'',

                       'firstPageLabel'=>'&lt;&lt;',

                       'prevPageLabel'=>'&lt;',

                       'nextPageLabel'=>'&gt;',	

                       'lastPageLabel'=>'&gt;&gt;',

                       'maxButtonCount'=>5,

                       'class'=>'CLinkPager'),

        'cssFile'=>false,

        'template'=>'<div class="gridHeader">{pager}</div>{items}<div class="gridFooter">{summary}{pager}</div>',

    )); ?>



These are my steps:

  1. load the admin which contains CGridView.

  2. From pagination click on the page 3.

  3. If I am not using "ajaxUpdate"=>false, the url in address bar is still the same as http://localhost/master/trunk/index.php?r=account/admin

only when I set the "ajaxUpdate"=>false, I will get the http://localhost/master/trunk/index.php?r=account/admin&Account_page=3

my question is how can I make the code is also working without changing the "ajaxUpdate".

Thanks a lot,

Daniel

Hi Daniel,

Do you have firebug on firefox or developer tools chrome? if so, open your firebug and go to the XHR requests. Filter the requests made on the console, as when you do AJAX calls, your address bar remains the same link as it was but on your AJAX calls you see the actual links.

If you set the ajaxUpdate= false, then no AJAX is performed and you will see the real link on the address bar.

Let me know if you have problems setting firebug for firefox. I think that is why is causing confusion.

Hi Antonio,

Thanks a lot. Somehow it is working now even when I remove the ajaxUpdate=>false. Still, I could not understand why since the url creation for buttons are outside the CGridView declaration.

I did a mistake, Although, I borrowed your code, I tested it not from the button but from my link thats why I still see problem, see portion of code below:


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

            'id'=>'account-grid',

            'dataProvider'=>$dataProvider,

            'selectableRows' => 2,

            'ajaxUpdate'=>false,

            'columns'=>array(

                    array(

                        'class'=>'CCheckBoxColumn',

                        'id'=>'rows_to_deleted',

                        'htmlOptions'=>array('style'=>'text-align: center; width: 25px;'),

                    ),

                    array(

                        'name'=>'AccountNo',

                        'type'=>'raw',

                        [color="#FFFF00"]'value'=>'CHtml::link(CHtml::encode($data->AccountNo), array("view", "id"=>$data->ID, "Account_page"=>$page))',[/color]

                        'htmlOptions'=>array('style'=>'text-align: center; width: 60px;'),

                    ),

...



Quick solution remove this link and use the button view.

Last question for this topic is how could I put as the value of "Account-page" instead of $page in order to make it work?

Once again, thanks a lot. I learn the XHR as well today ;)

It should always work Daniel as with or without AJAX the URLs are taken from the HREF. Now I dare you to find a solution for the SORTing :)

Happy is working of you

ps: about XHR and firebug or chrome development tools console is a must have tool Daniel. Once you get your hands onto it, you wont be able to develop-debug without it. Hint: check the javascript breakpoints now coming with those consoles.

Cheers!

Hi Antonio,

I used firebug for some times, but never understand the XHR functionality until yesterday ;)

The part that I could not understand fully is that the $buttons definitions are outside the gridview definition, why the ajax call can update the $buttons.url while its definition is outside the gridview?


array(

                        'name'=>'AccountNo',

                        'type'=>'raw',

                        'value'=>'CHtml::link(CHtml::encode($data->AccountNo), array("view", "id"=>$data->ID, "Account_page"=>[color="#FF0000"]$page[/color] ))',

                        'htmlOptions'=>array('style'=>'text-align: center; width: 60px;'),

                    ),



What should I put as the $page there? If I used $page it always gave me 0 after I move to other page (clicking on other page through pagination).


$page = Yii::app()->getRequest()->getParam('News_page',false);

About sorting, what would be the case? I eager to learn it from you.

I am trying the sum of columns on each page, now.

Thanks a lot.

Dear Daniel,

After looking at the code you I saw a couple of mistakes. Here is the correct solution to all of them





// you forgot to get Account Model page instead of News_page <-- that was my example

$page = Yii::app()->getRequest()->getParam('Account_page',false); // corrected now


// you forgot to include the CButtonColumn declaration

// here the correct way

// setting up the class

$buttons = array('class'=>'CButtonColumn');


// do we have a Account_page parameter?

$page = Yii::app()->getRequest()->getParam('Account_page',false);


// if yes, modify the link

if( $page ){

    foreach(array('view','update','delete') as $id){

        $buttons[$id.'ButtonUrl'] = 'Yii::app()->controller->createUrl("'.$id.'",array("id"=>$data->primaryKey,"Account_page"=>'.$page.'));';

    }

}


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

            'id'=>'account-grid',

            'dataProvider'=>$dataProvider,

            'selectableRows' => 2,

           'ajaxUpdate'=>false, // doesnt matter but ok

            'columns'=>array(

                    array(

                        'name'=>'AccountNo',

                        'type'=>'raw',

                        // here you put "page" as parameter, changed to "Account_page"

                        'value'=>'CHtml::link(CHtml::encode($data->AccountNo), array("view", "id"=>$data->ID, "Account_page"=>$dataProvider->pagination->currentPage ))',

                        'htmlOptions'=>array('style'=>'text-align: center; width: 60px;'),

                    ),

                    'AccountName',

                    array(

                        'name'=>'Level',

                        'htmlOptions'=>array('style'=>'text-align: center; width: 50px;'),

                    ),

                    array(

                        'name'=>'NormalBalance',

                        'htmlOptions'=>array('style'=>'text-align: center; width: 50px;'),

                    ),

                    array(

                        'name'=>'Classification',

                        'type'=>'raw',

                        'value'=>'$data->Classification',

                        'htmlOptions'=>array('style'=>'text-align: left; width: 120px;'),

                    ),

                   // we do not declare the buttons column outside, we declare the array

                   // that holds the declaration of the CButtonColumn and its buttons

                   // and then include them here

                    $buttons,

            ),

        'pager'=>array('cssFile'=>false,

                       'header'=>'',

                       'firstPageLabel'=>'&lt;&lt;',

                       'prevPageLabel'=>'&lt;',

                       'nextPageLabel'=>'&gt;', 

                       'lastPageLabel'=>'&gt;&gt;',

                       'maxButtonCount'=>5,

                       'class'=>'CLinkPager'),

        'cssFile'=>false,

        'template'=>'<div class="gridHeader">{pager}</div>{items}<div class="gridFooter">{summary}{pager}</div>',

    )); 



Hope I help you Daniel,

Cheers!