unchanged
Title
CListView AJAX filtering
This tutorial shows how to filter CListView items by AJAX, and it's compatible with disabled JavaScript usersIn my case this has been done to filter users list String filter ------------------ ### View In our **view** file we have something like this ~~~ [php] $this->widget('zii.widgets.CListView', array( 'dataProvider'=>$dataProvider, 'itemView'=>'viewList', 'sortableAttributes'=>array( 'id'=>'cronologico', 'transaction' ), 'id'=>'ajaxListView', )); ~~~ We now add a form with a text field (remember to change form action), the value of the field get updated with the GET parameter ~~~ [php] echo CHtml::beginForm(CHtml::normalizeUrl(array('message/index')), 'get', array('id'=>'filter-form')) . CHtml::textField('string', (isset($_GET['string'])) ? $_GET['string'] : '', array('id'=>'string')) . CHtml::submitButton('Search', array('name'=>'')) . CHtml::endForm(); ~~~ and a JQuery script that sends AJAX request after a short delay (this reduces DB queries) ~~~ [php] Yii::app()->clientScript->registerScript('search', "var ajaxUpdateTimeout; var ajaxRequest; $('input#string').keyup(function(){ ajaxRequest = $(this).serialize(); clearTimeout(ajaxUpdateTimeout); ajaxUpdateTimeout = setTimeout(function () { $.fn.yiiListView.update( // this is the id of the CListView 'ajaxListView', {data: ajaxRequest} ) }, // this is the delay 300); });" ); ~~~ ### Controller action This is the controller action ~~~ [php] public function actionIndex( $string = '' ) { $criteria = new CDbCriteria(); if( strlen( $string ) > 0 ) $criteria->addSearchCondition( 'username', $string, true, 'OR' ); $dataProvider = new CActiveDataProvider( 'User', array( 'criteria' => $criteria, ) ); $this->render( 'index', array( 'dataProvider' => $dataProvider ) ); } ~~~ Extended use ------------------ I had to implement a more sophisticated filter for my offer CListView: selecting checkBoxes with integer value the search had to be filtered with an IN condition. CheckBoxes get selected by the GET parameter ### View ~~~ [php] echo CHtml::checkBoxList('category', (isset($_GET['category'])) ? $_GET['category'] : '', $category[$key], array( 'class'=>'categoryFilter', ) ); ~~~ Then i had to add this javaScript for the AJAX filtering ~~~ [javascript] $('.categoryFilter').change(function(){ category = $('.categoryFilter').serialize(); $.fn.yiiListView.update( 'ajaxListView', {data: category} ); }); ~~~ ### ControllerCheckBoxes GET parameters are variable (in my case up to 21) so I had to use an array in my controller. ~~~ [php] public function actionIndex( $string = '', array $category = array() ) { $criteria = new CDbCriteria(); if( strlen( $string ) > 0 ) { $criteria->addSearchCondition( 'title', $string, true, 'OR' ); $criteria->addSearchCondition( 'description', $string, true, 'OR' ); } if( count( $category ) > 0 ) $criteria->addInCondition( 'category', $category ); $dataProvider = new CActiveDataProvider( 'Offer', array( 'criteria' => $criteria, ) ); $this->render( 'index', array( 'dataProvider' => $dataProvider ) ); } ~~~ May be usefull to add buttons that selects and deselects all checkBoxes ~~~ [php] echo CHtml::button('All', array('id'=>'selectAll')) . CHtml::button('None', array('id'=>'selectNone')); ~~~And register the following JavaScript ~~~ [javascript] $('#selectAll').click(function(){ $('.categoryFilter').attr('checked','checked') category = $('.categoryFilter').serialize(); $.fn.yiiListView.update( 'ajaxListView', {data: category} ); }); $('#selectNone').click(function(){ $('.categoryFilter').removeAttr('checked') category = $('.categoryFilter').serialize(); $.fn.yiiListView.update( 'ajaxListView', {data: category} ); }); ~~~