Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jquery Autocomplete for 2 input field (same class)

I have two input fields like this:

<input name="accountCode" class="accountCode grid_2"/>
<input name="accountCode" class="accountCode grid_2"/>

I want to have an autocompleter on both of these fields. I have written the following JavaScript:

$(".accountCode").autocomplete(
{
    minLength : 1,
    source : function(request, response) {
        $.ajax({                            
            url : baseUrl + "Autocomplete/Account?accountCode=" + $(this).val(),
            dataType : "json",
            success : function(data) {
                response($.map(data, function(item) {
                    return {
                        value : item.accountCode,
                        desc : item.accountName
                    }
                }));
            }
        });
    },
    focus : function(event, ui) {                   
        $(this).val(ui.item.accountCode);
        return false;
    },
    select : function(event, ui) {
        // $("#category").val( ui.item.name );
        $(this).val(ui.item.value);
        // $( "#project-description" ).html( ui.item.desc );
        return false;
    }
}).data("autocomplete")._renderItem = function(ul, item) {
    return $("<li></li>").data("item.autocomplete", item).append(
        "<a><strong>" + item.value + " </strong>" + item.desc + "</a>")
    .appendTo(ul);
}; 

Of course, my server returns JSON data with 2 field: accountCode and accountName.

I want both inputs to use the custom renderer in _renderItem so that this will be displayed in the list:

"<a><strong>" + item.value + " </strong>" + item.desc + "</a>"

For the first field, it works perfectly, but for second field it only displays the accountCode from item.value.

I've checked that the JSON received from the server is the same in both cases so the problem is in the Javascript.

Do you know why this problem exist?

like image 970
Thang Nguyen Avatar asked Sep 14 '11 03:09

Thang Nguyen


2 Answers

Your problem is right here:

}).data("autocomplete")._renderItem

When the autocomplete widget binds to an element, each element gets its own distinct autocomplete data value. Then, when you grab the .data('autocomplete') to set the _renderItem function, you'll only get one of the two distinct data objects; so the first text field gets your custom renderer but the second one stays with the default renderer.

You can see what's going on by playing with this HTML:

<div id="a"></div>
<div id="b"></div>
<div id="out"></div>

And this jQuery:

var $out = $('#out');

$out.append('<p>Setting both to {a:"a"}</p>');
$('#a').data('pancakes', { a: 'a' });
$('#b').data('pancakes', { a: 'a' });
$out.append('<p>#a.a = ' + $('#a').data('pancakes').a + '</p>');
$out.append('<p>#b.a = ' + $('#b').data('pancakes').a + '</p>');

$out.append('<p>Setting "div".a to "x"</p>');
$('div').data('pancakes').a = 'x';
$out.append('<p>#a.a = ' + $('#a').data('pancakes').a + '</p>');
$out.append('<p>#b.a = ' + $('#b').data('pancakes').a + '</p>');

And a live demo: http://jsfiddle.net/ambiguous/DM8Wv/2/

Check what the jsfiddle does and you should see what's going on.

You can iterate through the autocomplete fields and set the _renderItem individually with something like this (untested code):

$(".accountCode").autocomplete({
    //...
}).each(function() {
    $(this).data('autocomplete')._renderItem = function(ul, item) {
        //...
    };
});

You could also bind the autocomplete widget to each element individually but keeping it all together and using each to set the _renderItem keeps everything nicely organized.

like image 133
mu is too short Avatar answered Oct 14 '22 10:10

mu is too short


Very nice solution with respect to:

.each(function() {
    $(this).data('autocomplete')._renderItem = function(ul, item) {
        //...
    };
});

The purpose of calling auto-complete with the same class is when you want to have the same help list to show up in several similar fields.

like image 22
Steffan Avatar answered Oct 14 '22 10:10

Steffan