Lazy Loading Type Pager For Clistview Or Cgridview

Hi All,

I thought of sharing something that I just made. I needed a pager in Yii that would work something like lazy loading. I scoured the internet but didn’t find anything suitable. Then I came across few articles which would work as the basis for lazy loading. To make the pager, I did the following:

  • extended CBasePager

  • extended CListView

  • created a view which just showed items

  • modified the controller function to return paginated data with ajax

The articles I have followed are:

Extending CListView

Partial rendering in CListView

  1. Creating new Pager:

I extended CBasePager class just to create a LOAD MORE button. I have put a span element instead of a tag since a tag would refresh the grid every time it is clicked. The code is as follows:




<?php

/**

 * class TOCPager

 * - extend pager to make pager for TOC for content

 * - add 

 */ 

class exPager extends CBasePager

{

	public function run()

	{

		$currentPage = $this->currentPage;

		$pageCount = $this->pageCount;




		if($currentPage < $pageCount)

		{

			list($controller, $action) = explode('/', Yii::app()->urlManager->parseUrl(Yii::app()->request));

			$theUrl = Yii::app()->request->url;

			//var_dump($this->getOwner());

			echo '

				<div class="load-msg">

					<input type="hidden" id="pgNumber" value="'.($currentPage+1).'"/>

					<span id="paginator">LOAD MORE...</span>

				</div>

			';

			$cs = Yii::app()->getClientScript();

			$script = '

				$("#paginator").click(function(e)

				{

					var containerElement = $(this).parent().parent().parent().attr("id");

					var itemsList = $(this).parent().parent().prev();

					var nextPage = $(this).prev().val()*1;

					var pageCount = '.$pageCount.'*1;


					var pgNumber = $(this).prev();

					$.ajax({

						url:"'.$theUrl.'?ajax="+containerElement+"&page="+(nextPage+1),

						success:function(returnData)

						{

							$(itemsList).append(returnData); //append the content

							pgNumber.val(nextPage+1);


							if(pgNumber.val() == pageCount)

								$("#paginator").parent().attr("style", "display:none;");

						}

					});

				});

			';

			$cs->registerScript('#script', $script, CClientScript::POS_READY);

		}

	}

}



  1. Next, I extended CListView just to return the items, not with wrapping tags. The code is as follows:



<?php

Yii::import('zii.widgets.CListView');

class PlainCListView extends CListView

{

	public $preItemsTag = '';

	public $postItemsTag = '';


	public function renderItems()

	{

	    echo $this->preItemsTag."\n";

	    $data=$this->dataProvider->getData();

	    if(($n=count($data))>0)

	    {

	        $owner=$this->getOwner();

	        $render=$owner instanceof CController ? 'renderPartial' : 'render';

	        $j=0;

	        foreach($data as $i=>$item)

	        {

	            $data=$this->viewData;

	            $data['index']=$i;

	            $data['data']=$item;

	            $data['widget']=$this;

	            $owner->$render($this->itemView,$data);

	            if($j++ < $n-1)

	                echo $this->separator;

	        }

	    }

	    else

	        $this->renderEmptyText();

	    echo $this->postItemsTag."\n";

	}


	public function run()

    {

        $this->renderContent();

    }

}



  1. Thirdly, I created a small view that uses previously created PlainCListView for showing the list. An example of the view is as follows:



<?php

	$this->widget('application.widgets.PlainCListView', array(

		'dataProvider'=>$posts,

		//'afterAjaxUpdate'=>'clickEvents',

		//'ajaxType'=>'POST',

		'itemView'=>'_post',

		'viewData'=>array('userForumStatus'=>$userForumStatus, 'isLocked'=>$isLocked),

		'summaryText'=>'',

		'id'=>$listID,

		'template'=>'{items}',

	));

?>



  1. Lastly, in the controller, I have followed the idea presented here. My sample code is as follows:



		if(Yii::app()->request->isAjaxRequest && isset($_GET['ajax']) && $_GET['ajax'] === $listID) 

		{

			$this->renderPartial('_posts_list_nopager', array(

				'posts' => $posts,

				'listID' => $listID,

				'userForumStatus'=>$userForumStatus,

				'isLocked'=>isset($parentForum['locked'])?$parentForum['locked']:0

			));


			Yii::app()->end();

	    }



So, when you run everything, you will get a pager ‘LOAD MORE’ at the bottom of the list. If you click it, additional rows/items will be appended to the existing items block.

I hope this is helpful to everybody. I had hell of a time searching for right materials for this.

Good work!!! This should be in Tips, Snippets and Tutorials Section.

[color="#006400"]NOTE: moved to proper section - "Tips, Snippets and Tutorials" instead of "Bug Discussions"[/color]

Ver nice. This must be in wikis.

Thanks for sharing.

Thanks everybody!

Can anyone tell me how to use exPager Class?