I'm trying to get the autocomplete plugin to populate one textbox with the university name and another with the university code. The code below returns results and populates the university name textbox, but I can't figure out how to populate another input.
I've tried following this example, but came across problems to even call the webmethod. One odd thing about this was that it seemed that the ajax was called before the autocomplete was attached to the textbox where the user types. Not sure what was triggering the js to call the autocomplete method.
I had to combine parts from the above with the jquery ui doc on autocomplete using json (link). But I still don't know how to get the second input to be populated as in the first example.
any ideas?
Here's the jquery and html
<script language="javascript" type="text/javascript">
$(function () {
$("#university").autocomplete({
source: function (request, response) {
$.ajax({
type: "POST",
url: "AutoComplete.asmx/GetUniversities",
dataType: "json",
data: "{ 'data': '" + request.term + "' }",
contentType: "application/json; charset=utf-8",
success: function (data) {
response($.map(data, function (item) {
return {
value: item.Descr,
UnivCode: item.UnivCode
}
}));
}
});
}
});
});
</script>
<div class="ui-widget">
<label for="university">University: </label>
<input id="university" type="text"/>
<label for="universityID">ID: </label>
<input id="universityID" type="text" />
</div>
Here's my .net webmethod
using System;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Collections.Generic;
using System.Web.Script.Services;
using System.Text;
using System.Data;
[ScriptService()]
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class AutoComplete : System.Web.Services.WebService
{
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public List<University> GetUniversities(string data)
{
List<University> UniversityList = new List<University>();
try
{
clsDataBase db = new clsDataBase();
DataTable dt = new DataTable();
StringBuilder sql = new StringBuilder();
Dictionary<string, object> parms = new Dictionary<string, object>();
sql.Append(" SELECT univ_code ");
sql.Append(" , INITCAP(univ_desc) AS descr ");
sql.Append(" FROM lk_university ");
sql.Append(" WHERE UPPER(univ_desc) LIKE UPPER(?) ");
sql.Append(" ORDER BY univ_desc ");
parms.Add("university", "%" + data + "%");
dt = db.executeParmQuery(sql.ToString(), parms);
DataView dv = new DataView(dt);
ArrayList filteredList = new ArrayList();
foreach (DataRowView drv in dv)
{
University university = new University();
university.UnivCode= drv["univ_code"].ToString();
university.Descr = drv["descr"].ToString();
UniversityList.Add(university);
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
//return null;
}
//}
return UniversityList;
}
public class University
{
string _value;
public string value
{
get { return _Descr + " (" + _UnivCode + ")"; }
}
string _Descr;
public string Descr
{
get { return _Descr; }
set { _Descr = value; }
}
string _UnivCode;
public string UnivCode
{
get { return _UnivCode; }
set { _UnivCode = value; }
}
}
}
EDIT
I was able to get it working by adding the select event. In my previous testing I had it in there, but in the wrong spot (initially nested in the success event). Also had to add the three lines in the success event that set value: item.Descr, Descr: item.Descr, and UnivCode: item.UnivCode. I don't quite understand what these are referencing or what they're doing, since the actual setting of inputs is done in the select event where I specify the actual id's of the inputs ($('#university').val(ui.item.Descr);), but this was needed to get the code to work.
Here's the working jquery without any other changes to the html or the .net code.
<script language="javascript" type="text/javascript">
$(function () {
$("#university").autocomplete({
source: function (request, response) {
$.ajax({
type: "POST",
url: "AutoComplete.asmx/GetUniversities",
dataType: "json",
data: "{ 'data': '" + request.term + "' }",
contentType: "application/json; charset=utf-8",
success: function (data) {
response($.map(data, function (item) {
return {
value: item.Descr,
Descr: item.Descr,
UnivCode: item.UnivCode
}
}));
}
});
},
select: function (event, ui) {
$('#university').val(ui.item.Descr);
$('#universityID').val(ui.item.UnivCode);
return false;
}
});
});
I was able to get it working by adding the select event. In my previous testing I had it in there, but in the wrong spot (initially nested in the success event). Also had to add the three lines in the success event that set value: item.Descr, Descr: item.Descr, and UnivCode: item.UnivCode. I don't quite understand what these are referencing or what they're doing, since the actual setting of inputs is done in the select event where I specify the actual id's of the inputs ($('#university').val(ui.item.Descr);), but this was needed to get the code to work.
Here's the working jquery without any other changes to the html or the .net code.
$(function () {
$("#university").autocomplete({
source: function (request, response) {
$.ajax({
type: "POST",
url: "AutoComplete.asmx/GetUniversities",
dataType: "json",
data: "{ 'data': '" + request.term + "' }",
contentType: "application/json; charset=utf-8",
success: function (data) {
response($.map(data, function (item) {
return {
value: item.Descr,
Descr: item.Descr,
UnivCode: item.UnivCode
}
}));
}
});
},
select: function (event, ui) {
$('#university').val(ui.item.Descr);
$('#universityID').val(ui.item.UnivCode);
return false;
}
});
});
I have been through this pain using MVC and the object that you return needs to have a label property (displayed in the drop down list) and a value property (the actual selection value - UnivCode).
The key to it is having a select method defined on your autocomplete box that accepts 2 arguments (e.g. select: function(e, ui){ ... do stuff ...; return false; }). The trick here is the return false to prevent jQuery from running the default event handler.
You can then use ui.item.label to get the display value, and ui.item.value to get the code.
I used a separate method that accepted ui.item and then wrote the values to hidden inputs.
If I can get my code together, I will post an example.
Example:- This example is using a text box called Autocomp1_display to which the autocomplete is attached. The displayItem method then writes the display value of the selected item to this text box, and puts the selected value into a hidden span.
$j("#Autocomp1_display").autocomplete({
source: function(request, response){
$j.ajaxSetup({cache: false});
$j.ajax({
url: "AutoComplete.asmx/GetUniversities"
type: "GET",
data: request,
dataType: "json",
success: function (data) {
request.term="";
response(data);
}
});
},
cache: false,
select: function(e, ui){
displayItem("Autocomp1", ui.item);
Autocomp1_HasSelections = true;
setAutocompleteState("Autocomp1_display", Autocomp1_IsMultiSelect, Autocomp1_HasSelections);
$j('#Autocomp1').change();
return false;
},
focus: function(event, ui){
if (ui.item.label){
$j(this).val(ui.item.label);
} else {
$j(this).val(ui.item.value);
}
return false;
}
});
The select event makes use of the displayItem method as below
//Function to write the entries into the text box
function displayItem(target, dataObject) {
var displayValue = dataObject.label.replace('\n','');
var existingSpan = false;
existingSpan = document.getElementById("span_" + displayValue);
if (!existingSpan) {
var span = $j("<span>").text(displayValue); //Create a new span tag to display the selected value
span.attr({ id: "span_" + dataObject.value });
var hiddenFld = $j("<input>").attr({ type: "hidden" }).val(dataObject.value); //Create a div object to store the code value
hiddenFld.addClass(target + "IdField").css("visibility", "hidden").css("height", 0).attr({ id: target, name: target }); //Format the div
var a = $j("<a>").addClass(target + "remove").attr({
href: "javascript:",
title: "Remove " + displayValue
}).text("x").appendTo(span); //Define the "x" to remove the span
hiddenFld.appendTo(span); //Append the div to the span
span.insertBefore("#" + target + "_display"); //Insert span before the concealed text box
$j("#" + target).attr({ value: dataObject.value }); //Store the ID value related to the selected item
$j("#" + target + "_display").val("").css("top", 2); //Store the ID value related to the selected item
//$j("#" + target + "_display").flushCache(); //Flush the cache for the autocomplete control
} else {
alert("This item has already been selected");
}
}
The setAutocompleteState method:-
function setAutocompleteState(targetName, IsMultiSelect, HasSelections) {
if (!IsMultiSelect && HasSelections) {
$j("#" + targetName).autocomplete("option", "disabled", true);
} else {
$j("#" + targetName).autocomplete("option", "disabled", false);
}
}
The isMultiSelect and HasSelections define whether or not the autocomplete should be enabled, and the targetName is simply the ID of the textbox that has been "autocompleted"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With