You are viewing revision #1 of this wiki article.
This is the latest version of this article.
Remember-filters-gridview is one of the must-use extension on all of my project. However, it lacks of storing the page and sort variables of the grid view.
In addition, Page size dropdown is also useful that I hope some day it can squeeze into the core of the CGridView.
Based on the Page size dropdown, I would like to try to write a wiki on how to store the page and sort variables on the similar way to the Page size dropdown.
First, in your controller (my example is ExtractController), make it like this:
public function actionAdmin() {
$model = new Extract('search');
// This is as suggested on the Remember-filter-gridview,
// to clear the state of the filter.
// I add four line to clear the page and sort as well.
// Note: somehow, I need to put those lines above the
// EButtonColumnWithClearFilters, otherwise, it will not clear the
// Extract_page and Extract_sort states.
if (intval(Yii::app()->request->getParam('clearFilters')) == 1) {
Yii::app()->user->setState('Extract_page', null);
unset($_GET['Extract_page']);
Yii::app()->user->setState('Extract_sort', null);
unset($_GET['sort']);
EButtonColumnWithClearFilters::clearFilters($this, $model); //where $this is the controller
}
// This portion of code is belongs to Page size dropdown.
$pageSize = Yii::app()->user->getState('extractPageSize', Yii::app()->params['defaultPageSize']);
if (isset($_GET['pageSize'])) {
$pageSize = (int) $_GET['pageSize'];
Yii::app()->user->setState('extractPageSize', $pageSize);
unset($_GET['pageSize']);
}
// I achieve similar result to Page size with the Extract_page.
// ELSE body is needed to handle the differences of case back to first page from
// other pages and call to admin page from anywhere. The ajax method is the key to
// differentiate it. Call to admin would not be an ajax call, while the call from
// pagination is an ajax call (by default. since you can make it non ajax as well).
if (isset($_GET['Extract_page'])) {
$extractPage = (int) $_GET['Extract_page'] - 1;
Yii::app()->user->setState('Extract_page', $extractPage);
unset($_GET['Extract_page']);
} else if (isset($_GET['ajax'])) {
Yii::app()->user->setState('Extract_page', 0);
}
// Sort is little bit different. Do not UNSET the sort variable
// since it will be directly used by the CGridView.
// The ELSE body is used to handle non ajax calls to admin page.
if (isset($_GET['sort'])) {
$extractSort = $_GET['sort'];
Yii::app()->user->setState('Extract_sort', $extractSort);
} else if(Yii::app()->user->hasState('Extract_sort')) {
$_GET['sort'] = Yii::app()->user->getState('Extract_sort');
}
$this->render('admin', array(
'model' => $model,
'pageSize' => $pageSize,
));
}
Second, the model (Extract.php). We only need to change the search method :
public function search() {
$criteria = new CDbCriteria;
$criteria->compare('name', $this->name, true);
$criteria->compare('productNumber', $this->productNumber, true);
$criteria->compare('specification', $this->specification, true);
$sort = new CSort;
$sort->defaultOrder = 'name ASC';
$sort->attributes = array(
'name' => 'name',
'productNumber' => 'productNumber',
'specification' => 'specification',
);
$sort->applyOrder($criteria);
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
'sort' => $sort,
'pagination' => array(
// This line below is the only addition made to the model by Page size dropdown.
'pageSize' => Yii::app()->user->getState('extractPageSize', Yii::app()->params['defaultPageSize']),
// This line below is the only addition made to the model in
// choosing the page to be displayed.
'currentPage' => Yii::app()->user->getState('Extract_page', 0),
),
));
}
That's all we should do.
Future works The code in actionAdmin is little bit messy to me, can anyone give some feedback to tidy up little bit? In addition, I am a beginner in PHP and Yii!, I don't quite understand the consequences in term of performance and security to store those variables in state.
I admit that this is not purely my idea, but still I would like to share this to get some feedback as well as help others with some problem with me.
there are extensions you can use for pageSize Selection
EListView
and here PageSize
and my modified version :EPageSize in github
it's possible to use this extension without touch the action and you model class ^-^
just do some works in your view file
Re: there are extensions you can use for pageSize Selection
Thank you @yiqing95 for the information. I am trying to update this wiki to include your suggestion. One thing how can I include the widget into the BootGridView ( I want to put the widget in the Summary text of the BootGridView)? I saw the example in your readme for BootGridView, it seems you use EBootGridView and no where I can see you put the widget.
Thanks,
Daniel
@adinugro you can extend your own one
i just extend the BootGridView class ,and do some extra thing . but this do not affect to the EPageSize just use it with CGridView and CListView .
if you want make it displayed in {summary} section , just rewrite the renderSummary function ,it's not so difficult doing that .
just give you a reference , it 's not ready for publish ^-^ (you see i am Chinese ,and not ready use the English for my own codes ):
<?php /** * Created by JetBrains PhpStorm. * User: yiqing * Date: 12-2-16 * Time: 上午11:16 * To change this template use File | Settings | File Templates. */ Yii::import('ext.bootstrap.widgets.BootGridView'); class EBootGridView extends BootGridView { protected $rowSetKeys = array(); public $rowIdPrefix = 'gr_'; public function init() { parent::init(); $this->rowSetKeys = $this->dataProvider->getKeys(); } /** * @param $row * ad row id property to the generated tr element */ public function renderTableRow($row) { $rowId = $this->rowIdPrefix . $this->rowSetKeys[$row]; if ($this->rowCssClassExpression !== null) { $data = $this->dataProvider->data[$row]; echo '<tr class="' . $this->evaluateExpression($this->rowCssClassExpression, array('row' => $row, 'data' => $data)) . '" id="' . $rowId . '">'; } else if (is_array($this->rowCssClass) && ($n = count($this->rowCssClass)) > 0) echo '<tr class="' . $this->rowCssClass[$row % $n] . '" id="' . $rowId . '">'; else echo '<tr id="' . $rowId . '">'; foreach ($this->columns as $column) $column->renderDataCell($row); echo "</tr>\n"; } //----------------------------<总是在template中可用listPager>--------------------------------------- /** * @var array * config for the CListPager */ public $listPager = array(); /** * @return mixed * using EBootGridView::listPager config to render the listPager */ public function renderListPager() { if (!$this->enablePagination) return; $pager = array(); $class = 'CListPager'; if (is_array($this->listPager)) { $pager = $this->listPager; if (isset($pager['class'])) { unset($pager['class']); } }else{ throw new CException('the listPager must be an array ,which is a config array for the Class CLinkPager'); } $pager['pages'] = $this->dataProvider->getPagination(); if(!isset($pager['htmlOptions']) || ! isset($pager['htmlOptions']['onchange'])){ //if not set the onchange ,the default behavior is ajax pagination $pager['htmlOptions']['onchange'] = "if(this.value!=''){\$.fn.yiiGridView.update('{$this->getId()}',{url:this.value}); /*window.location=this.value;*/};"; } if ($pager['pages']->getPageCount() > 1) { //echo '<div class="' . $this->pagerCssClass . '">'; $this->widget($class, $pager); //echo '</div>'; }else{ $this->widget($class, $pager); } } //----------------------------<总是在template中可用listPager/>----------------------------------------- //.........<允许在模板中使用epageSize 扩展>................................................. public $ePageSize = array(); /** * @return mixed * using EBootGridView::listPager config to render the listPager * ------------------------------------------------ * 有bug 原因未知 待查..... * ------------------------------------------------ */ public function renderEPageSize() { if(!$this->enablePagination) return; $widget = array(); $class = 'ext.PageSize.EPageSize'; if(is_string($this->ePageSize)){ $class = $this->ePageSize ; } else if(is_array($this->ePageSize)){ $widget = $this->ePageSize; if(isset($widget['class'])) { $class = $widget['class']; unset($widget['class']); } } $widget['gridViewId'] = $this->getId(); $widget['pageSize'] = Yii::app()->request->getParam('pageSize',null); if(! isset($widget['defaultPageSize'])){ $widget['defaultPageSize'] = 10; } if(! isset($widget['pageSizeOptions'])){ $widget['pageSizeOptions'] = array(5=>5, 10=>10, 25=>25, 50=>50, 75=>75, 100=>100); } /* $this->widget('ext.PageSize.EPageSize', array( 'listViewId' => '<?php echo $this->class2id($this->modelClass); ?>-grid', 'pageSize' => Yii::app()->request->getParam('pageSize',null), 'defaultPageSize' => 10 , // may use this : Yii::app()->params['defaultPageSize'], 'pageSizeOptions'=> array(5=>5, 10=>10, 25=>25, 50=>50, 75=>75, 100=>100), // you can config it in main.php under the config dir . Yii::app()->params['pageSizeOptions'],// Optional, you can use with the widget default )); */ $pagination = $this->dataProvider->getPagination(); if($pagination->getPageCount()>1){ $this->widget($class,$widget); } } //.........<允许在模板中使用epageSize 扩展/>................................................ //----------<松弛模板 在模板中可用用上面配置到的键 >-------------------------------------------------------------------------------------------- /** * @var array * ----------------------- * 参考CButtonColumn::buttons * ----------------------- */ public $templates = array(); /** * Renders a section. * This method is invoked by {@link renderContent} for every placeholder found in {@link template}. * It should return the rendering result that would replace the placeholder. * @param array $matches the matches, where $matches[0] represents the whole placeholder, * while $matches[1] contains the name of the matched placeholder. * @return string the rendering result of the section * ------------------------------------------------------------ * 拷贝自CBaseListView * ------------------------------------------------------------- */ protected function renderSection($matches) { $method='render'.$matches[1]; if(method_exists($this,$method)) { $this->$method(); $html=ob_get_contents(); ob_clean(); return $html; }elseif(! empty($this->templates) && is_array($this->templates)){ $widgetTemplateName = $matches[1]; //template Token if(isset($this->templates[$widgetTemplateName])){ $widgetConfig = $this->templates[$widgetTemplateName]; return $this->_renderWidgetTemplate($widgetConfig); } } return $matches[0]; } /** * @param array $widgetConfig * @return mixed * @throws CException */ protected function _renderWidgetTemplate($widgetConfig=array()){ if(isset($widgetConfig['class'])){ $widgetClass = $widgetConfig['class']; unset($widgetConfig['class']); return $this->widget($widgetClass,$widgetConfig,true); }else{ throw new CException('you must specify the widget \'s class for using the templates '); } } //----------<松弛模板 在模板中可用用上面配置到的键/ >-------------------------------------------------------------------------------------------- }
And how about this approach?
As I already wrote many times, I'm friend of very simple native solutions. What do you think about this?
http://www.yiiframework.com/wiki/462/yii-for-beginners-2/#hh10
@Daniel:
The idea is very simple. I just save the whole GET variable to session. And if user wants to display the same grid again and does not specify GET parameters, the old are used.
Because filter, pagination and sorting are just data sent via GET request in format:
Re: And how about this approach?
@rackycz Thank you for your feedback. Unfortunately, I could not comment to your suggestion since I am still not getting the idea on how you keep sort and filter the gridview. Can you elaborate more on simple working example? Thanks in advance.
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.