Difference between #4 and #3 of CListView AJAX filtering

unchanged
Title
CListView AJAX filtering
unchanged
Category
Tutorials
unchanged
Tags
CListView, AJAX, filters
changed
Content
This tutorial shows how to filter CListView items by AJAX, and it's compatible
with disabled JavaScript users  
In 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}
    );
});
~~~

### Controller
CheckBoxes GET parameters are variable (in my case up to 21) so I had to
use an array in my controller.

CheckBoxes 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}
        );
    });
~~~