Using filters on CGridView with CActiveDataProvider is easy, but with CArrayDataProvider it is a bit tricky.
To use the filters you have to create a separate model class. I used some code from the following forum topic: link
Here is some example code:
Copy and include this class into your application.
/** * Filterform to use filters in combination with CArrayDataProvider and CGridView */ class FiltersForm extends CFormModel { public $filters = array(); /** * Override magic getter for filters */ public function __get($name) { if(!array_key_exists($name, $this->filters)) $this->filters[$name] = null; return $this->filters[$name]; } /** * Filter input array by key value pairs * @param array $data rawData * @return array filtered data array */ public function filter(array $data) { foreach($data AS $rowIndex => $row) { foreach($this->filters AS $key => $value) { // unset if filter is set, but doesn't match if(array_key_exists($key, $row) AND !empty($value)) { if(stripos($row[$key], $value) === false) unset($data[$rowIndex]); } } } return $data; } }
// Create filter model and set properties $filtersForm=new FiltersForm; if (isset($_GET['FiltersForm'])) $filtersForm->filters=$_GET['FiltersForm']; // Get rawData and create dataProvider $rawData=User::model()->findAll(); $filteredData=$filtersForm->filter($rawData); $dataProvider=new CArrayDataProvider($filteredData); // Render $this->render('index', array( 'filtersForm' => $filtersForm, 'dataProvider' => $dataProvider, ));
$columns = array( array( 'header'=>CHtml::encode('Name'), 'name'=>'username', ), array( 'header'=>CHtml::encode('Organisation'), 'name'=>'organisation', ), ); $this->widget('zii.widgets.grid.CGridView', array( 'id'=>'area-grid', 'dataProvider'=>$dataProvider, 'columns'=>$columns, 'filter'=>$filtersForm, ));
Total 12 comments
Awesome post :D
Blacklisting possible user input and using eval(), damn scary indeed!
Why don't make a more rigid and secure code using switch with cases for your comparison operators, at the same time teaching readers how to do this properly?
@karmraj : the problem is not with the filters, but with CArrayProvider you created. try something like this :
when you dont have column 'id' in your data, then you need to defined the unique key for CArrayDataProvider manually, as the default value is column with the name 'id'. In the example above the keyField is assigned to branch_id column, change the value "branch_id' to whatever primary key you have in you data.
@marcovtwout : i got little bit solution regarding this issue. when i will change my table column name branch_id to id then above issue will solve except the filter is not working...
@marcovtwout : Thanx for quick response. I have already declare branch_id as primary key in branch table. And now i have also set filter false in columns attributes. But still getting same result.
$columns = array(
array( 'header'=>CHtml::encode('branch name'), 'name'=>'branch_name', 'filter'=>false, ),);1.
Your problem has nothing to do with the filtering, I think (try setting filter=>false). Have you set your column branch_id in table Branch to be the primary key? Also, consider naming the column "id", calling it branch_id is redundant, and it plays nice with Yii's default expectations.
You can also try to set the property keyAttribute to 'branch_id' in the construction of the dataprovider: http://www.yiiframework.com/doc/api/1.1/CActiveDataProvider#keyAttribute-detail
Following my code which i have use. I dont get what is an issue. I am constantly getting same error as : Property "Branch.id" is not defined. There no field in my branch table name as id.
FiltersForm model file
class FiltersForm extends CFormModel { public $filters = array();
/** * Override magic getter for filters */ public function __get($name) { //print_r($name); exit; if(!array_key_exists($name, $this->filters)) $this->filters[$name] = null; return $this->filters[$name]; } /** * Filter input array by key value pairs * @param array $data rawData * @return array filtered data array */ public function filter(array $data) { foreach($data AS $rowIndex => $row) { foreach($this->filters AS $key => $value) { // unset if filter is set, but doesn't match if(array_key_exists($key, $row) AND !empty($value)) { if(stripos($row[$key], $value) === false) unset($data[$rowIndex]); } } } return $data; }}
Controller Action
public function actionAdminNew() { $filtersForm=new FiltersForm; if (isset($_GET['FiltersForm'])) $filtersForm->filters=$_GET['FiltersForm']; // Get rawData and create dataProvider $rawData=Branch::model()->findAll(); $filteredData=$filtersForm->filter($rawData); $dataProvider=new CArrayDataProvider($filteredData); // Render $this->render('adminNew', array( 'filtersForm' => $filtersForm, 'dataProvider' => $dataProvider, )); }view file :
<?php $columns = array( array( 'header'=>CHtml::encode('branch id'), 'name'=>'branch_id', ), array( 'header'=>CHtml::encode('branch name'), 'name'=>'branch_name', ), ); //print_r($dataProvider); exit; ?> <?php $this->widget('zii.widgets.grid.CGridView', array( 'id'=>'branch-grid', 'dataProvider'=>$dataProvider, 'columns'=>$columns, 'filter'=>$filtersForm, )); ?>Whoops, totally missed out on this wiki article. Just updated wrong example code in Controller, it was not using critical filter function!
I looked at the other comments but decided to keep the article as is: filter the data BEFORE creating the data provider, bit easier. :)
Thanks for your nice post. You will also need to set "totalItemCount" before returning data in the "filter" function, to get pagination works correctly after filtering.
i use Chessspider approach, but with minor modification on the filter() function to refresh dataprovider rawData so the pagination will be correct and filter can be perform nicely as we want to.
so here's the filter() function
I had to modify the filter() method to this:
and the controller Render-call to this:
I copied it over 1:1, literally. Yet it still refuses to do any filtering whatsoever.
It shows all data, and the filter box appears. However when I enter text in it, no filtering occurs. There is no change whatsoever.
Any ideas what could be the problem?
Leave a comment
Please login to leave your comment.