The ERememberFiltersBehavior extension adds up some functionality to the default possibilites of CActiveRecord/Model implementation.
It will detect the search scenario and it will save the filters from the GridView during navigation. This comes handy when you need to store them for later use. For heavy navigation and heavy filtering, this functionality can be activated by just a couple of lines.
1217
Requirements
Yii 1.1
Download
Donate
Click here to donate
Resources
Remember-filters-extension
Report a bug
Usage
To use this extension, just copy this file to your components/ directory, add ‘import’ => ‘application.components.ERememberFiltersBehavior’, […] to your config/main.php and paste the following code to your behaviors() method of your CActiveRecord/Model
public function behaviors() {
return array(
'ERememberFiltersBehavior' => array(
'class' => 'application.components.ERememberFiltersBehavior',
),
);
}
For up to date documentation see: Remember-filters-extension
This extension has also a pair Clear Filters Gridview
it is very easy, you use like any other behavior you bind at the behaviors() method
download the zip file
put the php file from the zip in the protected/c[color="#1C2837"]omponents folder[/color]
[color="#1C2837"]3. edit your protected/config/main.php configuration file and add to [/color][color="#1C2837"]‘import’ => ‘application.components.ERememberFiltersBehavior’[/color]
[color="#1C2837"]4. go to the model/CActiveRecord you are using for your search display and add to behaviors(), this method might not exists, so in that case just add this method[/color]
class MyClassName extends CActiveRecord {
......
// add or extend the below function
public function behaviors() {
return array(
'ERememberFiltersBehavior' => array(
'class' => 'application.components.ERememberFiltersBehavior',
),
);
}
public function search() {
// your existing search method that will filter the grid, no need to touch it here
}
.....
}
$model=new Product('search');
$model->unsetAttributes(); // clear any default values
if (intval(Yii::app()->request->getParam('clearFilters'))==1) {
EButtonColumnWithClearFilters::clearFilters($this,$model);//where $this is the controller
}
if (isset($_GET['pageSize'])) {
Yii::app()->user->setState('Product_pageSize',(int)$_GET['pageSize']);
unset($_GET['pageSize']);
}
if(isset($_GET['Product']))
{
$model->attributes=$_GET['Product'];
}
else
{
$model->status = Product::ACTIVE;
}
$merge = new CDbCriteria;
$merge->order = '`name` ASC';
$this->render('admin',array(
'model'=>$model, 'merge'=>$merge,
));
I need to put the else clause because I want by default it is display only active product. If I implement the remember filter extension, my code become
$model=new Product('search');
if (intval(Yii::app()->request->getParam('clearFilters'))==1) {
EButtonColumnWithClearFilters::clearFilters($this,$model);//where $this is the controller
}
if (isset($_GET['pageSize'])) {
Yii::app()->user->setState('Product_pageSize',(int)$_GET['pageSize']);
unset($_GET['pageSize']);
}
$merge = new CDbCriteria;
$merge->order = '`name` ASC';
$this->render('admin',array(
'model'=>$model, 'merge'=>$merge,
));
Where can I put the else clause if the filter is not set?
[color=#222222][font=Arial, sans-serif][size=2]I’ve updated the extension to include support for defaults. Please setup the behavior in your model file, and there you can now set defaults. Donation is welcome for implementing this functionality in for you.[/size][/font][/color]
Not yet. It is work in progress, but stuck on the way how we can create behaviors for [color=#454545][font=arial, helvetica, sans-serif][size=2]CActiveDataProvider. Refer to this ticket for the problem I encountered. [/size][/font][/color]
I am using remember-filters-gridview and like it very much. I also want to remember sort order; but see the problem of not being able to attach a behavior to CActiveDataProvider.
Why not extend CActiveDataProvider and implement the necessary functionality there? I have already extended CActiveDataProvider as MyActiveDataProvider, which I use in all my model.search() methods. You can override CActiveDataProvider__construct() to do the same things as you would have done in onAfterConstruct. Of course make sure to call the parent __construct() before or after your code as appropriate.
I’d do this myself but I’m not yet clear what needs to be added to CActiveDataProvider to remember the sorting. The fetchData() method does the real work; it calls applyOrder() to add the ordering. Looks like maybe the answer is to override CActiveDataProvider.fetchData(). Instead of calling $sort->applyOrder(), it would retrieve and re-apply the saved sort criteria. But I’m not too clear on the implementation.
I was able to add this function without modifying CActiveDataProvider at all. Just put this code into actionAdmin() of your controller. In my case I put it in the class which is the parent of all my controllers, so it’s inherited.
in MyParentController.php / actionAdmin() :
$sortCacheID = $this->id . '_sort';
$sorts = array();
foreach ($_GET as $g=>$gval) {
if (strpos($g, '_sort')) {
$sorts[$g]=$gval;
}
}
if ($sorts != array()) {
// user requested sort(s); overrides anything set previously and cache the sorts
Yii::app()->user->setState($sortCacheID, $sorts);
} else {
// no sorts in get; use cached values if present
$sorts = Yii::app()->user->getState($sortCacheID, array());
foreach ($sorts as $s=>$sval) {
$_GET[$s] = $sval; // as if they were requested; will be consumed by grid widget in admin view
}
}
yes, click page number 7, go to edit one of the items and when go back to the the list. the filter option was saved but it is back on page 1 instead of 7
Here’s my solution, which does not use the CPagination methods as mentioned. It’s a bit long, but works. (Part of the reason for extending the framework classes is I’ve removed another part of my solution which includes a drop-down control in each admin view to select the pageSize for this model and remember it in persistent storage, which is outside the scope of this thread.)
This solution would be trivial (just part [4]) except for the fact that CPagination omits the pageNo on the first page. This causes problems. In order to fix this you must extend CPagination, extend CActiveDataProvider to use it, and extend all your models to use the new ActiveDataProvider class.
extend CPagination as MyPagination and override createPageUrl to always include the pageNo in the URL.
class MyPagination extends CPagination
{
// always put the page number in. See MyController.actionAdmin() for usage
public function createPageUrl($controller,$page)
{
$params=$this->params===null ? $_GET : $this->params;
// if($page>0) // page 0 is the default
$params[$this->pageVar]=$page+1;
// else
// unset($params[$this->pageVar]);
return $controller->createUrl($this->route,$params);
}
}
extend CActiveDataProvider as MyActiveDataProvider. override getPagination to use MyPagination
class MyActiveDataProvider extends CActiveDataProvider {
private $_pagination;
// override to create instance of MyPagination
public function getPagination() {
if ($this->_pagination === null) {
//$this->_pagination=new CPagination;
$this->_pagination = new MyPagination;
if (($id = $this->getId()) != '')
$this->_pagination->pageVar = $id . '_page';
}
return $this->_pagination;
}
}
in all your models, change search() to use MyActiveDataProvider instead of CActiveDataProvider
public function search() {
$criteria = new CDbCriteria;
....
return new MyActiveDataProvider(get_class($this), array(
'criteria' => $criteria,
));
(either) extend CController as MyController. Make all your controllers extend from MyController. Each controller must define $modelClass. In this case, the child controllers don’t have an actionAdmin. (or) simply put the code fragment into the actionAdmin() of each controller.
public $modelClass = ''; // child must define actual Model name
...
actionAdmin()
...
// persist page number
$pageParam = ucfirst($this->modelClass) . '_page';
if (isset($_GET[$pageParam])) {
$page = $_GET[$pageParam];
Yii::app()->user->setState($this->id . '-page', (int) $page);
} else {
$page = Yii::app()->user->getState($this->id . '-page', 1);
$_GET[$pageParam] = $page;
}
...
it’s not working for me, after comming back it’s on page 1, while i left the page on page 7…
public $modelClass = '';
/**
* Manages all models.
*/
public function actionAdmin()
{
$model=new Daytrip('search');
//$model->unsetAttributes(); // clear any default values
//if(isset($_GET['Daytrip']))
//$model->attributes=$_GET['Daytrip'];
$pageParam = ucfirst($this->modelClass) . '_page';
if (isset($_GET[$pageParam])) {
$page = $_GET[$pageParam];
Yii::app()->user->setState($this->id . '-page', (int) $page);
} else {
$page = Yii::app()->user->getState($this->id . '-page', 1);
$_GET[$pageParam] = $page;
}
$this->render('admin',array(
'model'=>$model,
));
}
/**
* Retrieves a list of models based on the current search/filter conditions.
* @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
*/
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('id_daytrip',$this->id_daytrip);
$criteria->compare('daytrip',$this->daytrip,true);
$criteria->compare('city_id',$this->city_id);
$criteria->compare('active',$this->active);
return new MyActiveDataProvider('Daytrip', array(
'criteria'=>$criteria,
));
}