Thanks Lance for putting me on the right track. This answer is selectable and works in jquery-ui-1.11.4.
$.ui.autocomplete.prototype._renderMenu = function (ul, items) {
var self = this;
ul.append("<li class='ui-autocomplete-category' aria-label='header'><div class='listFullName listHeader'>Name</div><div class='listEmployeeID listHeader'>Employee ID</div><div class='listJobTitle listHeader'>Job Title</div></li>");
$.each(items, function (index, item) {
self._renderItemData(ul, item);
});
};
$.ui.autocomplete.prototype._renderItem = function (table, item) {
return $("<li>")
.data("item.autocomplete", item)
.append("<div class='listFullName'>" + item.label + "</div>" + "<div class='listEmployeeID'>" + item.value + "</div>" + "<div class='listJobTitle'>" + item.JobTitle + "</div>")
.appendTo(table);
};
$("#employeeLookup").autocomplete({
source: [
{ value: 1, label: "Bob Smith", JobTitle: "President" },
{ value: 2, label: "Bob Washington", JobTitle: "Vice-President" },
{ value: 3, label: "Bobby Fischer", JobTitle: "Secretary" },
{ value: 4, label: "Bobby Brady", JobTitle: "Treasurer" },
{ value: 5, label: "Bobby Socks", JobTitle: "Senior Vice-President" },
{ value: 6, label: "Barney Rubble", JobTitle: "Sidekick" },
{ value: 7, label: "Brenda Stevens", JobTitle: "Assistant Senior Vice-President" }
],
minLength:1
});
Here's the CSS I then add to format the columns:
.listFullName{
width:200px;
display:inline-block;
}
.listJobTitle{
width:150px;
display:inline-block;
}
.listEmployeeID{
width:100px;
display:inline-block;
}
Note that I add the 'ui-autocomplete-category' class to the header row to prevent it from being selectable in the results. I add the aria-label attribute to avoid a jQueryUI runtime exception apparently caused by encountering a list item that wasn't rendered using _renderItemData, although I did not do a deep dive into that.
Now, if you are pulling data via ajax, such as in the following example:
$("#employeeLookup").autocomplete({
source: function (request, response) {
// var id = $(this);
// alert(id);
$.ajax({
url: "Search.asmx/FindEmployee",
data: "{ 'partialName': '" + request.term + "'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function (data) { return data; },
success: function (data) {
response($.map(data.d, function (item) {
return {
FullName: item.FullName,
EmployeeID: item.Person_ID,
JobTitle: item.JobTitle,
label: item.FullName,
value:item.FullName
}
}))
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest);
}
});
},
minLength: 3,
delay: 500,
select: function (event, ui) {
alert("select" + ui.item.FullName);
}
});
You could change the _renderItem override to this:
$.ui.autocomplete.prototype._renderItem = function (table, item) {
return $("<li>")
.data("item.autocomplete", item)
.append("<div class='listFullName'>" + item.FullName + "</div>" + "<div class='listEmployeeID'>" + item.EmployeeID + "</div>" + "<div class='listJobTitle'>" + item.JobTitle + "</div>")
.appendTo(table);
};
In the Success event, jQueryUI is looking for "label" and "value" elements in the resulting array. You can map other elements as well for your own coding clarity, but "label" is the array element that jQueryUI Autocomplete will search/filter by, and "value" is the array element that JQueryUI Autocomplete will put into the html input once you select a value from the list.