Reputation: 10563
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
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
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
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
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
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