Jquery ui autocomplete populating hidden field with ID

10,556

Solution 1

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;
        }
    });
});

Solution 2

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"

Share:
10,556
Jerry
Author by

Jerry

Specialties: Programming: C#, MVC 3/4, ASP.NET 2.0/3.5/4.0/4.5, SQL, JavaScript, CSS, HTML, VBA, XML Libraries: jQuery, jQueryUI, Telerik MVC Controls, Log4Net Technologies: Visual Studio 2010/2012, Team Foundation Server, PeopleSoft Database: MS SQL Server, Oracle, MS Access

Updated on June 14, 2022

Comments

  • Jerry
    Jerry almost 2 years

    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;
                }
            });
        });
    
  • Duncan Howe
    Duncan Howe almost 13 years
    This is based on this tutorial/article here
  • Jerry
    Jerry almost 13 years
    I was able to get my issue resolved (see edit above), but was interested in trying to get your facebook style additions of fields working. I updated my .net object to return label and value, but wasn't getting any results back on the site. Typing in the AutoComp1_display textbox called the .net webmethod which returned results (I'm watching all traffic via fiddler), but no results show up under the textbox. There is a small blueish div about 5px in height that shows up as I type, but it has no values in it.
  • Jerry
    Jerry almost 13 years
    Had other questions about your code. On your end is it working as written above? Where do you define setAutocompleteState and what does it do? You declare Autocom1_HasSelections, but not Autocom1_IsMultiSelect, are these properties and the above method outside the scope of the objective to get autocomplete to populate a hidden field?
  • Jerry
    Jerry almost 13 years
    One last thing. What I want to do differently then what you're doing in your sample is to append the selected values as spans to a div below the input textbox, where each value will be on it's own line. Would this require any other changes to your code besides sending the id of the div to the display item function instead of the input textbox?
  • Duncan Howe
    Duncan Howe almost 13 years
    Jarek, this code is part of a much larger system and parts have been written generically to allow multiple autocompletes on a page, while the actual autocomplete control is rendered at runtime using MVC Html Extension methods. The setAutocomplete method is defined in the same file as the displayItem and simply sets the autocomplete to be disabled or not (see edit in the answer).
  • Duncan Howe
    Duncan Howe almost 13 years
    The HasSelections and IsMultiSelect are defined in a script tag as part of the control rendering. In response to your question does it run as written, yes it does - the only difference is we are using MVC so the URL property points to a Controller action that returns a JSON object (with label and value properties) which the autocomplete seems to like.
  • Jerry
    Jerry almost 13 years
    Thanks for your responses Duncan, but I ended up using a different plugin to make the autocomplete work plus get the facebook style selections. Plugin used is loopj.com/jquery-tokeninput and a small guide how to implement it asp.net/ajaxLibrary/…