Autocomplete multiple fields

This article is also available in the following languages:
By MartinLissmats
This short tutorial will show how to autocomplete data to multiple fields.
In this tutorial I will assume you have a working autocomplete function up and running already, as seen in http://book.cakephp.org/view/632/autoComplete.

In my case, I have a model called "Customer" which stores information about customers, such as customer address data. A second model is "Invoice". When I add a new invoice I want to bind it to a customer and also fetch certain customer information to be added to the invoice.

You will see that I am fetching data from the customer model with the intent to store it in the invoice model as well. This may seem redundant, but in my case, once an invoice is created and sent out to a customer, the invoice stored in the database is not supposed to change even if the customer data is updated afterwards.

Form view

Here are some snippets of how my view with all the forms for adding a new invoice looks. When including the javascript to create a new autocompleter take note that I have added the option afterUpdateElement with the value setCustomerValues which will call a custom javascript function called setCustomerValues after an item from the autocomplete list has been selected.

View Template:


...
<?php
echo $form->input('customer_id', array('type' => 'hidden'));
echo 
$form->input('addr_name');
echo 
$form->input('addr_street');
echo 
$form->input('addr_city');
?>
<div id="customer_choices" class="autocomplete"></div>
...


...
<div id="javascripts" style="display:none;">
<script type="text/javascript">new Ajax.Autocompleter("InvoiceAddrName", "customer_choices", "/customers/autocomplete/", { frequency: '0.6', afterUpdateElement : setCustomerValues }, {});
</script>
</div>
...

Autocomplete view

With a normal autocomplete view, you have a list of items with the data inside the li html element. To bake in hidden additional data that is ment to be sent to other input fields, I include the data as attributes to the li element.

View Template:


<ul>
<?php foreach($customers as $customer): ?>
    <li addr_street="<?php echo @$customer['Customer']['addr_street'];?>" addr_city="<?php echo @$customer['Customer']['addr_city'];?>" customer_id="<?php echo @$customer['Customer']['id'];?>"><?php echo $customer['Customer']['name'];?></li>
<?php endforeach; ?>
</ul>

The javascript

As you hopefully remember, we added the option to call a custom function called setCustomerValues after an item is selected in the autocomplete list. This function has to be created and you need to put it in a javascript file and make sure to include the javascript file in your view.

//Use -1 as "attr" parameter value to setValue to clear the element.
function setValue(element,attr) {
    var e = document.getElementById(element);
    if (e==null){return;}
    if (attr == -1) {e.value = '';} 
    else if (attr != null && attr != ' ' && attr != '') {e.value = attr;}
}

function setCustomerValues(text, li)
{
    setValue('InvoiceCustomerId',li.getAttribute('customer_id'));
    setValue('InvoiceAddrStreet',li.getAttribute('addr_street'));
    setValue('InvoiceAddrCity',li.getAttribute('addr_city'));
}

Comments

  • Posted 03/15/11 11:42:13 AM
    Hi! sorry guys! I feel so stupid. I didn't realize that i was using one external help from http://www.cakephp.bee.pl/ajax/autoComplete. Works the same als prototype's autocomplete but this work with jquery. I finded the solutions making everything new using prototype and MartinLissmats code.
  • Posted 03/14/11 12:09:34 PM
    Hi!
    I'm trying autocomplete multiple fields using the simple autocomplete help from http://book.cakephp.org/view/632/autoComplete and "jquery.autocomplete.min.js" that work like a charm just for a field but not for more. I need help with this, so I leave here my code and I hope samebody can help me:
    in my controller:
    function articulosAutoComplete() {
    $this->set('articulos', $this->Articulo->find('all', array(
    'conditions' => array(
    'Articulo.articulo LIKE' => '%'.$this->params['url']['q'].'%'),'limit' => $this->params['url']['limit'])));
    $this->layout = 'ajax';
    }
    I get all from "articulos" table, 3 rows. "id","articulo","desc_articulo"
    in my view:
    echo $ajax->autocomplete('articulo', '/articulos/articulosAutoComplete',
    array('class' => 'inputclient',
    'label' => 'Articulo',
    'updateElement' => 'function() { return true; }',
    'afterUpdateElement' =>'setArticleValues'));

    echo $form->input('desc_articulo', array('class' => 'inputstore', 'label' => 'Descripción'));
    Here I get everything in my autocomplete input "articulo". I'm not able to show description in my "desc_articulo" input

    in my autocomplete.ctp:




    'afterUpdateElement' =>'setArticleValues' is not working right, i have write an alert in setArticleValues but withot response...i'm not going in.
    What I'm doing bad??


    @gotech86

    just one question. Your code with onclick work? if is it, could you show me wath do you have in your view please?


    I apologize for my poor English, I hope you understand me.

    Thanks in advance.
  • Posted 05/12/10 09:28:23 AM
    I just made an onClick event in my autocomplete.ctp

    View Template:


        onclick="BestelregelProductId.value = '<?php echo @$product['Product']['id'];?>',
                 ProductGarantie.value = '<?php echo @$product['Product']['garantie'];?>',
                 ProductVoorraad.value = '<?php echo @$product['Product']['voorraad'];?>',
                 BestelregelPrijs.value = '<?php echo @$product['Product']['verkoop_prijs'];?>'
                "
    >
  • Posted 05/11/10 09:33:13 AM
    Hmm i tried this method but I can't get it working.

    Somehow my autosearch field dissapears after applying this, ( and its outside the hided div)

Comments are closed for articles over a year old