Friday, January 14, 2011

Creating an instant search box for the CListView

We have our index page, with a CListView displaying a list of items, in this case contacts.

We want a single "instant" search box, that will filter the contacts list instantly.

Your index.php view page should look something like this:
<?php
$this->breadcrumbs=array(
'Contacts',
);

$this->menu=array(
array('label'=>'Create Contact', 'url'=>array('create')),
array('label'=>'Manage Contact', 'url'=>array('admin')),
);

//this adds a javascript event listener to the search box that will query the server with each keystroke. yw0 is the id of the clistview. q is the id of the text input box:
Yii::app()->clientScript->registerScript('search', "
  $('input#q').keyup(function(){
  $.fn.yiiListView.update('yw0', {
  data: $(this).serialize()
  });
  return false;
});
");
?>

<h1>Contacts</h1>

<!-- add a search box: -->
<input type="text" id="q" name="q" />

<?php $this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_view',
)); ?>
Change your actionIndex function in your ContactController to look something like this:
public function actionIndex() {
  $model = new Contact($scenario='search');
  $model->unsetAttributes();
  $model->first_name = $_GET['q'];

  //add the ->search() call: 
  $this->render('index',array('dataProvider'=>$model->search()))
}

Now when you type in the field, it should filter the contacts by their first name.

Improvements:
  • change onkeyup so it fires with a few characters and after a small delay
  • add a new search() function that will search several attributes at once using "OR" instead of "AND". This can be done in the compare() function with the 4th argument.
  • Some heavy caching on the server so that the database is not overwhelmed.

9 comments:

  1. show error => Undefined index: q

    ReplyDelete
  2. you have to choose isset($_GET['q']) method , otherwise it show undefine q error :)

    ReplyDelete
  3. Wow this is great. thanks very much for this tutorial..... really really helpful. :)

    ReplyDelete
  4. I get some empty alert boxes popping up whenever I click on the objects returned from the search. I dont alert anything in my code, and this only occurs if I click on a returned result immediately after searching. has this issue ever come up for you?

    ReplyDelete
  5. Is it possible to add more than one of these boxes in order to filter by more than one element of the table?

    ReplyDelete
  6. Really nice job
    I have a book table and a tags table. I would like to be able to search by tags. Could you help me please, how could I do that?

    ReplyDelete
  7. Hello, your tutorial really help me, thank you very much...
    Now, how to combine "criteria" and "pagination"??

    I'm trying this, but not work:
    $criteria = new CDbCriteria(array(
    'order' => 'id DESC',
    ));

    $dataProvider=new CActiveDataProvider('TblBarang', array(
    'pagination'=>array('pageSize'=>4),
    'criteria'=>$criteria,
    ));

    $this->render('index',array(
    'dataProvider'=>$model->search(),
    'pagination'=>array('pageSize'=>4),
    'criteria'=>$criteria,
    ));

    Please, help me...

    ReplyDelete
  8. It's ok, i find the solution. This is my code at index.php:

    pagination = array('pageSize' => 5);
    $dataProvider->sort = array('defaultOrder' => 'tgl_upload DESC');
    $this->widget('bootstrap.widgets.TbListView',array(
    'dataProvider'=>$dataProvider,
    'itemView'=>'_view',
    'summaryText' => '', //untuk menghilangkan "Displaying 1 sd 10"
    'sortableAttributes'=>array(
    'tgl_upload'=>'Update Terbaru',
    ),
    ));
    ?>

    Thank you. :)
    Or do you have another solution??

    ReplyDelete