Home > Coding, PHP, Yii > Yii autocomplete widget example

Yii autocomplete widget example

Yii is simple. Yii is nice. Yii is coder-friendly. No, this is not a commercial brake, just my 2 cents regarding recent framework switching from CodeIgniter and Zend. I’m not gonna delve deep into the features it has, instead I’ll describe one witch I liked really really much. It gave me the possibility to quickly give a client the sight for sore eyes regarding one-to-many or many-to-many form populating.

In this example I will describe one-to-many example and you can pick up the pieces for something more complicated.

Ok, so we have let’s say Hotel as a model and Hotel Offer as something that can relate to only one Hotel. On the Hotel Offer create/update interface we would want to allow client to select one of many Hotels in the system. So, the first approach was a drop down field but after populating the database with more then 10 hotels this was not a viable solution. Ergo, the first insight to CJuiAutoComplete was made. After some example scanning and some self-proclaimed coding I came to a solution which is presented below:

protected/controllers/HotelController.php

public function actionAutocomplete () {
  if (isset($_GET['term'])) {
    $criteria=new CDbCriteria;
    $criteria->alias = "hotels";
    $criteria->condition = "hotels.name like '" . $_GET['term'] . "%'";

    $dataProvider = new CActiveDataProvider(get_class(Hotel::model()), array(
'criteria'=>$criteria,‘pagination’=>false,
));
    $hotels = $dataProvider->getData();

    $return_array = array();
    foreach($hotels as $hotel) {
      $return_array[] = array(
                    'label'=>$hotel->name,
                    'value'=>$hotel->name,
                    'id'=>$hotel->id,
                    );
    }

    echo CJSON::encode($return_array);
  }
}

A condition parameter of the CDbCriteria class can be tweaked if maybe I would want to include all results which include the letters type in the resulting auto complete drop down, not just those beginning with. Also don’t forget to add ‘autocomplete’ action to the ACL rules in the accessRules method.

Now we need to prepare the Hotel Offer. CJuiAutoComplete widget has one downside and that’s that it has to use the existing attribute of the model. Now, I haven’t find a way to specify the attribute as a relational field to some other model, so we have to add a hotels_name field in the HotelOffer model.

protected/models/HotelOffer.php


class HotelOffer extends CActiveRecord {
  public $hotels_name;

....

  public function afterFind() {
$this->hotels_name = $this->hotel->name;
  }
}

Now, all we need is to put the widget into the Hotel Offer form and we’re done for the day 🙂

protected/views/hotelOffer/_form.php

<div>
  <?php echo $form->label($model,Yii::t('messages','Hotel Name')); ?>
  <?php echo $form->hiddenField($model,'hotels_id',array()); ?>
  <?php $this->widget('zii.widgets.jui.CJuiAutoComplete',
    array(
      'model'=>$model,
      'attribute'=>'hotels_name',
      'source'=>$this->createUrl('hotel/autocomplete'),
      'htmlOptions'=>array('placeholder'=>'Any'),
      'options'=>
         array(
               'showAnim'=>'fold',
               'select'=>"js:function(hotel, ui) {
                  $('#HotelOffer_hotels_id').val(ui.item.id);
                         }"
                ),
      'cssFile'=>false,
    )); ?>
</div>
Categories: Coding, PHP, Yii
  1. Franck
    June 24, 2011 at 12:25 pm

    Thanks a lot! You make my day!

    Cheers Franck

  2. ernest
    January 3, 2012 at 10:28 pm

    thanks a lot!, only one issue, when the query throw out more than 10 results it just display 10 rows, could you help me

    I followed all your example

    • January 3, 2012 at 10:59 pm

      In the controller where you set the data provider, try setting pagination to false (didn’t try but I think this should work):

      $dataProvider = new CActiveDataProvider(get_class(Hotel::model()), array(
      ‘criteria’=>$criteria, ‘pagination’=>false,
      ));

  3. ernest
    January 3, 2012 at 11:22 pm

    Thanks a lot! it worked

  4. faisal
    February 2, 2012 at 11:56 am

    can you tell me what this is actually doing ?

    CActiveDataProvider(get_class(Hotel::model()), array(
    ‘criteria’=>$criteria, ‘pagination’=>false,

    • February 2, 2012 at 12:00 pm

      It gets the set of ActiveRecord objects based on the criteria stored in CDbCriteria object which you can use on most/some yii display widgets later.
      It basically generates the sql query, executes it, and store the result in objects as described.

  5. faisal
    February 2, 2012 at 12:12 pm

    thanks , i got it……… can u tell me plz in _form

    ‘select’=>”js:function(hotel, ui)

    what this hotel is? is it table name in data base , or something else?

    • February 2, 2012 at 12:15 pm

      Nah it’s just an argument in the callback function which is not used in this case. Not sure what kind of info it contains, you can check that with Firebug or something …

  6. faisal
    February 2, 2012 at 12:20 pm

    in which condition this argument can be use, becz i changed name of this argument, its still working

    • February 2, 2012 at 12:29 pm

      Yes, you can change the name of any argument at will basically.
      But this here is a small mistake actually, the first argument should be ‘event’ which is an object which contains the data regarding the browser event which led to this callback function (i.e. click, or mouseover or something else). It can be useful in certain situations, but not here. You can see this in http://jqueryui.com/demos/autocomplete/ under ‘events’ tab, ‘select’ type.

  7. faisal
    February 2, 2012 at 12:33 pm

    ok thanks, i am doing some changes in that,if i face some problem i will contact you.

  8. faisal
    February 3, 2012 at 5:25 am

    hi!
    there is some problem accouring , when i type “a” in hidden field, all data is showing starting with “f” also… i want to show data starting with only “a”……….. what i do?

  9. February 3, 2012 at 12:28 pm

    You’ve probably put the two ‘%’ signs in the autocomplete action in the line

    $criteria->condition = “hotels.name like ‘” . $_GET[‘term’] . “%'”;

    This line should be exactly as written here (except the field you are comparing to).

  10. faisal
    February 7, 2012 at 8:44 am

    can you tell me plz what is that , what we are giving to attribute???

    ‘attribute’=>’hotels_name’,

  11. faisal
    February 8, 2012 at 12:25 pm

    hi!
    there is some problem accouring , when i type “a” in hidden field, all data is showing starting with “f” also… i want to show data starting with only “a”……….. what i do?

    same problem accouring , which occurs earlier?

  12. March 28, 2012 at 10:08 am

    Hi,

    I’ve created a form using yii in that autocomplete i need to perform for pick up the values of city, state and zipcode of it.. I created seperate table in my memberbook_update DB in that i filled the data for city state and zipcode.. I need to retrieve the data from db as autocmplete and i need to save same data in another table coulmns.. i created seperate model for each table.. I’m not able to do the operation.. Plaese any one help me how to do that..

  13. vis
    April 4, 2012 at 10:23 am

    Does not working showing me a blank page can any one help me ???

  14. vis
    April 4, 2012 at 10:51 am

    It was a model syntax problem but still it does not suggest me the Hotel name …

    plz help me…

  15. sharif
    August 7, 2012 at 10:55 am

    hotels_id is not defined in model how to fix it????

  16. Martin H
    September 19, 2012 at 1:39 am

    Not to ruin your day, but a line like

    $criteria->condition = “hotels.name like ‘” . $_GET[‘term’] . “%'”;

    is a HUGE security issue… Now everybody can do with your database whatever they feel like.

    • September 19, 2012 at 10:11 pm

      Nice catch.
      Though I think Yii is smart and that it checks the condition attribute of the DBCriteria object for malicious characters, like ‘;’ and escapes the single quotes as well.
      Not 100% sure on this one since I didn’t look at their code, and it’s definitely worth checking.. If you’re into Yii (since I gave it a brake a while back) you can tell us here if this is true or not…

  17. Faisal
    September 21, 2012 at 2:20 am

    I have implemented it successfully but the only problem is the appearance of pop list matching to the typed text in the field. how to customize it, the list shows bullet ed items which do not look good.
    Thanks
    Faisal

  18. February 15, 2014 at 3:56 pm

    $criteria=new CDbCriteria;
    $criteria->alias = “hotels”;
    $criteria->condition = “hotels.name like ‘” . $_GET[‘term’] . “%'”;

    I smell danger here…….

    you can use this code though….

    $criteria=new CDbCriteria;
    $criteria->alias = “hotels”;
    $criteria->condition = “hotels.name like ‘” . $_GET[‘term’] . “%'”;
    $crtieria->addSearchCondition(“hotels.name”,’$_GET[‘term’] ) ;

  19. sucipto
    March 31, 2015 at 5:20 am

    you can use this code too…

    $criteria->condition = “hotels.name like :hotelsName”;
    $criteria->params = array(‘:hotelsName’ => trim($_GET[‘term’]).’%’);

  1. No trackbacks yet.

Leave a reply to ernest Cancel reply