Jquery ui自动完成使用ID填充隐藏字段

时间:2011-05-04 21:21:35

标签: jquery asp.net json jquery-ui autocomplete

我正在尝试使用自动完成插件来填充一个带有大学名称的文本框和另一个带有大学代码的文本框。下面的代码返回结果并填充大学名称文本框,但我无法弄清楚如何填充另一个输入。

我尝试过这个example,但是甚至在调用web方法时遇到了问题。关于这一点的一个奇怪的事情是,似乎在自动完成附加到用户键入的文本框之前调用了ajax。不知道是什么触发了js来调用自动完成方法。

我必须使用json(link)将上面的部分与自动完成的jquery ui doc结合起来。但我仍然不知道如何在第一个例子中填充第二个输入。

任何想法?

这是jquery和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> 

这是我的.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; }
        }
    }
}

修改

我能够通过添加select事件来使其工作。在我之前的测试中,我在那里,但在错误的位置(最初嵌套在成功事件中)。还必须在设置值的成功事件中添加三行:item.Descr,Descr:item.Descr和UnivCode:item.UnivCode。我不太明白这些是什么引用或它们正在做什么,因为输入的实际设置是在select事件中完成的,其中我指定了输入的实际id($('#university')。val(ui) .item.Descr);),但这需要让代码工作。

这是工作jquery,没有对html或.net代码进行任何其他更改。

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

4 个答案:

答案 0 :(得分:9)

我能够通过添加select事件来使其工作。在我之前的测试中,我在那里,但在错误的位置(最初嵌套在成功事件中)。还必须在设置值的成功事件中添加三行:item.Descr,Descr:item.Descr和UnivCode:item.UnivCode。我不太明白这些是什么引用或它们正在做什么,因为输入的实际设置是在select事件中完成的,其中我指定了输入的实际id($('#university')。val(ui) .item.Descr);),但这需要让代码工作。

这是工作jquery,没有对html或.net代码进行任何其他更改。

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

答案 1 :(得分:1)

我使用MVC经历了这种痛苦,并且您返回的对象需要具有label属性(显示在下拉列表中)和value属性(实际选择值 - UnivCode)。

它的关键是在自动完成框中定义了一个接受2个参数的select方法(例如select:function(e,ui){... do stuff ...; return false;})。这里的技巧是返回false以防止jQuery运行默认事件处理程序。

然后您可以使用ui.item.label获取显示值,使用ui.item.value获取代码。

我使用了一个接受ui.item的单独方法,然后将值写入隐藏输入。

如果我可以将我的代码放在一起,我会发布一个例子。

实施例: - 此示例使用名为Autocomp1_display的文本框,其中附加了自动完成。然后,displayItem方法将所选项的显示值写入此文本框,并将所选值放入隐藏的跨度中。

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

select事件使用displayItem方法,如下所示

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

setAutocompleteState方法: -

function setAutocompleteState(targetName, IsMultiSelect, HasSelections) {
    if (!IsMultiSelect && HasSelections) {
        $j("#" + targetName).autocomplete("option", "disabled", true);
    } else {
        $j("#" + targetName).autocomplete("option", "disabled", false);
    }
}

isMultiSelect和HasSelections定义是否应启用自动完成,而targetName只是已经“自动完成”的文本框的ID

答案 2 :(得分:0)

与自动完成控件一起使用的样式

.acarea { padding:3px 3px 0; margin:0 auto; background-color:#fff; cursor:text; }
.acarea div {border:1px solid #aaa; }
.acarea input {border:0px; display:inline;}
.acarea span { display:block; width:auto; margin:0 3px 3px 0; padding:3px 20px 4px 8px; position:relative; float:left; text-indent:0; background-color:#eee; border:1px solid #333; -moz-border-radius:7px; -webkit-border-radius:7px; border-radius:7px; color:#333; font:normal 11px Verdana, Sans-serif; }
.acarea span a { position:absolute; right:8px; top:2px; color:#666; font:bold 12px Verdana, Sans-serif; text-decoration:none; }
.acarea span a:hover { color:#ff0000; }
.ui-menu .ui-menu-item { white-space:nowrap; padding:0 10px 0 0; }

自动完成控件的库函数

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

//function to load the existing data as entries
//targetName is the id of the control being rendered
//existingEntries is an array of objects that contain a label and value property (at least!!)
function loadItems(targetName, existingEntries){
    for (i=0;i<existingEntries.length;i++) {
        displayItem(targetName, existingEntries[i]);
    } //End of for loop
} //End of function

function setAutocompleteState(targetName, IsMultiSelect, HasSelections) {
    if (!IsMultiSelect && HasSelections) {
        $j("#" + targetName).autocomplete("option", "disabled", true);
    } else {
        $j("#" + targetName).autocomplete("option", "disabled", false);
    }
}

MVC扩展方法呈现的代码

<script language="javascript">
var Autocomp1_existingEntries = null;
var Autocomp1_IsMultiSelect = false;
var Autocomp1_HasSelections = false;
</script>

<div class="acarea" id="Autocomp1_acarea"><div class="ui-helper-clearfix"><input id="Autocomp1_display" type="text" /></div></div>

<script type="text/javascript" language="javascript">
$j(document).ready(function () {
$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;
}});
})

if (Autocomp1_existingEntries != null){
    loadItems("Autocomp1", Autocomp1_existingEntries);
    Autocomp1_HasSelections = true;
    setAutocompleteState("Autocomp1_display", Autocomp1_IsMultiSelect, Autocomp1_HasSelections);
}

$j("#Autocomp1_acarea").click(function() {
    $j("#Autocomp1_display").focus();
});

$j(".Autocomp1remove", document.getElementById("Autocomp1_acarea")).live("click", function() {
    var spanDiv = $j(this).parent().parent();
    $j(this).parent().remove();
    Autocomp1_HasSelections = false;
    var Autocomp1_nodeCounter = 0;

    for (Autocomp1_nodeCounter = 0;Autocomp1_nodeCounter < spanDiv[0].childNodes.length; Autocomp1_nodeCounter++){
        if (spanDiv[0].childNodes[Autocomp1_nodeCounter].nodeName.toLowerCase()=="span"){
            Autocomp1_HasSelections = true;     break;
        }
    }

    setAutocompleteState("Autocomp1_display", Autocomp1_IsMultiSelect, Autocomp1_HasSelections);
    if ($j("#Autocomp1_acarea span").length === 0) {
        $j("#Autocomp1_display").css("top", 0).val("");
    }
    $j('#Autocomp1').change();
});

这是我用于渲染自动完成控件并使其将所选值存储在div中的代码的完整性。随意按摩它,让它为你工作。

答案 3 :(得分:0)

我编写了一个包装JQuery UI自动完成小部件的Asp.Net WebControl。 WebControl提供了一个属性:OnClientSelection,您可以将其设置为javascript函数名称。 在幕后,它所做的正是你所做的指定'选择'动作。 我写了关于如何使用控件的文档。

您可以在以下网址找到它:

http://autocompletedotnet.codeplex.com/

希望它可以提供帮助