Martin
Martin

Reputation: 10563

jQuery autocomplete _renderItem issue with multiple inputs to trigger autocomplete

Quick explaination: I have 3 inputs first_name, last_name and contact_number. They all have the class name autocomplete. e.g.

<input type="input" name="first_name" id="first_name" class="autocomplete">
<input type="input" name="last_name" id="last_name" class="autocomplete">
<input type="input" name="contact_number" id="contact_number" class="autocomplete">

I use the autocomplete class as a selector for initiating the jQuery UI autocomplete function (see code below) such that filling in any of these will result in an ajax search using all 3 inputs. Because I use all 3 fields to do the search the result has to be in a specific place (not under each input as is normally the case) so I use a div with a table inside which in turn displays the results. This is possible by overriding the internal _renderItem function (see code below).

This all works perfectly fine, however, only for the very first input in the form e.g. first_name. The other inputs all show up the dropdown li list below their respective inputs. It seems the _renderItem override is ignored for subsequent inputs. I have tried swapping around the inputs and whichever is first works correctly and the others don't. Any suggestions as to how I could fix the behaviour?

    $(document).ready(function() {
        $(".autocomplete").autocomplete({
            search: function(event, ui) {
                $("#autocompleteoutput table tbody").empty();
                $("#autocompleteoutput").css("display", "inline");
            },
            source: function(request, response) {
                jQuery.ajax({
                    url: "'.site_url('reservations/search_customer').'",
                    type: "post",
                    dataType: "json",
                    data: {
                        first_name: $("#first_name").val(),
                        last_name: $("#last_name").val(),
                        contact_number: $("#contact_number").val(),
                        '.$this->security->get_csrf_token_name().' : "'.$this->security->get_csrf_hash().'"
                    },
                    success: function(data) {
                        response(jQuery.map(data, function(item) {
                            return {
                                diner_id: item.diner_id,
                                first_name: item.first_name,
                                last_name: item.last_name,
                                dialing_code: item.dialing_code,
                                country_id: item.country_id,
                                contact_number: item.contact_number,
                                email: item.email
                            }
                        }))
                    }
                })
            }
        })
        .data( "autocomplete" )._renderItem = function( ul, item ) {
            return $( "<tr class=\"customerselect\" data-dinerid=\"" + item.diner_id + "\" data-fname=\"" + item.first_name + "\" data-lname=\"" + item.last_name + "\" data-countryid=\"" + item.country_id + "\" data-num=\"" + item.contact_number + "\" data-email=\"" + item.email + "\"></tr>" )
                .data( "item.autocomplete", item )
                .append( "<td><span class=\"icon-user\">" + item.first_name + " " + item.last_name + "</span></td>")
                .append( "<td><span class=\"icon-phone\">(+" + item.dialing_code + ") " + item.contact_number + "</span></td>" )
                .append( "<td><span class=\"icon-mail\">" + item.email + "</span></td>" )
                .appendTo($("#autocompleteoutput table tbody"));
        };
    });

Upvotes: 5

Views: 6788

Answers (5)

amigatra
amigatra

Reputation: 1

$('.autocomplete').each(function(i, el) {
    $(el).autocomplete({
        source: function(request, response) {
            $.ajax({
                url: "/Actual/Provision",
                type: 'POST',
                dataType: "json",
                data: {'term': request.term},
                success: function(data) {
                    response(data);
                },
                error: function(data) {
                    alert('failed to load autocomplete source data');
                }
            });
        },
        minLength: 1,
        select: function(event, ui) {
            $(this).parent().find("input[name='submission_provision[]']").val(ui.item.name);
            $(this).parent().find("input[name='submission_part_age[]']").val(ui.item.part_age);
            $(this).parent().find("input[name='submission_part_smr[]']").val(ui.item.part_smr);
            $(this).parent().find("input[name='submission_labour_age[]']").val(ui.item.labour_age);
            $(this).parent().find("input[name='submission_labour_smr[]']").val(ui.item.labour_smr);

            return false;
        },
        change: function(event, ui) {
            if ($(this).val() == '') {
                $(this).parent().find(".provision-ref").val("");
            }
        }

    }).data("ui-autocomplete")._renderItem = function(ul, item) {
        console.log(ul);
        return $("<li>")
            .append("<a>" + item.name + "</a>")
            .appendTo(ul);
    };
});

Upvotes: 0

Farhan Jamil
Farhan Jamil

Reputation: 1

Thanks you solved my problem. I implemented it by 'create' function

$.extend(proto, {
    _initSource: function () {
        if (this.options.html && $.isArray(this.options.source)) {
            this.source = function (request, response) {
                response(filter(this.options.source, request.term));
            };
        } else {
            initSource.call(this);
        }
    },

    create: function () {
        $(this).data('ui-autocomplete')._renderItem = function (ul, item) {
            return $("<li></li>")
                .data("item.autocomplete", item)
                .append($("<a></a>")[this.options.html ? "html" : "text"](item.EmployeeHtml))
                .appendTo(ul);
    };
}

Upvotes: 0

Cari
Cari

Reputation: 1007

Both of the above answers pointed me in the right direction, but in the end, it looked like this (includes some updates to jquery-ui) for me:

$('.autocomplete').each(function(i, el) {
    $(el).data('ui-autocomplete')._renderItem = function(ul, item) {
        // Do stuff
    };
});

Upvotes: 8

user2380877
user2380877

Reputation: 121

This works for me too, especially if the input element generated dynamically :

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

Upvotes: 12

TWickz
TWickz

Reputation: 632

The .data("autocomplete") here returned only the first element's autocomplete data. Try using this method separately for each input after assigning the autocomplete control.

I mean like this

 function myRenderFunc(ul,item){
     // code for the _renderItem method
 }

 $(".autocomplete").autocomplete({
        //your autocomplete code
 })

 $('#first_name').data( "autocomplete" )._renderItem = myRenderFunc;
 $('#last_name').data( "autocomplete" )._renderItem = myRenderFunc;
 $('#contact_number').data( "autocomplete" )._renderItem = myRenderFunc;

I tried this right now and it worked for me. Should work for you too.

Upvotes: 13

Related Questions