具有混合文本/ ID搜索的jQuery UI自动完成

时间:2010-07-21 13:40:19

标签: jquery jquery-ui jquery-ui-autocomplete

我在使用jQuery的自动完成小部件时遇到了很多麻烦。我正在使用服务器中的键/值对列表。

我有以下要求:

如果用户从窗口小部件中选择一个值,我想将ID传递给服务器。

如果用户没有选择值并输入原始文本,或者修改了已经选择的值,我希望清除ID字段,只需要将原始文本发送到服务器。

假设someAjaxFunction返回自动完成小部件所需的对象数组:{label:label, value:key}

最初,我将自动完成小部件设置为:

$(input).autocomplete({
    source: sourceFunction,
    minLength: 1
});

即使将鼠标悬停在其中一个项目上,更改选择也会将$(输入)引用的文本框中的文本更改为基础键,而不是标签。从用户交互的角度来看,这是非常不受欢迎的 - 事实上,我正在研究这个问题的原因是因为我正在构建的网站的用户一直对他们输入的文本感到困惑,似乎变成了随机数字!

我在文本框下添加了一个隐藏字段,并实现了select()和focus()事件,以便隐藏ID,如下所示:

$(input).autocomplete({
    source: sourceFunction,
    minLength: 1
    focus: function(event, ui) {
        $(idField).val(ui.item.value);
        $(this).val(ui.item.label);
        return false;
    },
    select: function(event, ui) {
        $(idField).val(ui.item.value);
        $(this).val(ui.item.label);
        return false;
    },
    minLength: 1
});

当用户坚持使用自动完成下拉列表提供的脚本时,这很有效。该ID被隐藏并正确提交给服务器。不幸的是,如果用户想要在框中输入一些自由格式文本并根据该值进行搜索,则不会重置ID字段,并且先前选择的ID将提交给服务器。这也很令人困惑。

jQuery UI自动完成文档列出了change事件,并声明item参数的ui属性将设置为所选项。我想我可以在按键上重置隐藏的id字段,并在更改自动完成时重新填充ID。不幸的是,除了按键事件捕获不应重置ID的一大堆按键之外,还需要管理上述return false事件中的select语句文本框中的文本可防止change事件正确分配ui.item。

所以现在我被卡住了 - 我真的不知道还有什么我可以尝试制作它看起来应该默认支持的小部件支持功能。要么这个过程比它应该更复杂,要么我错过了一些非常明显的东西。我已经完成了所有可用的事件和所有示例,然后空手而归。实际上,即使是jQuery UI页面上的“自定义数据和显示”示例也会遇到这个问题。

我可以在服务器端添加一些黑客来覆盖这个,但我真的更愿意能够在客户端级别执行此操作。

我还希望坚持使用jQuery UI自动完成小部件,而不是切换到另一个小部件。

4 个答案:

答案 0 :(得分:2)

我正在进行自动完成的方法是创建一个包含输入的容器div。当我选择一个元素时,我将一个包含span的链接添加到容器中,然后隐藏输入框。

链接和范围的样式使其看起来像一个带有X的按钮,并具有一个单击事件处理程序以从DOM中删除条目,清除隐藏字段,并在单击时重新显示输入框。因此,当选择一个项目时:

  <div class="container">
    <a href="#"><span>Selected Item</span></a>
    <input id="myautocomplete" type="text" />
    <input type="hidden" name="myvalue" value="1" />
  </div>

当未选择某个项目时:

 <div class="container">
    <input id="myautocomplete" name="myautocomplete" type="text" />
    <input id="myvalue" name="myvalue" type="hidden" value="" />
  </div>

这样,您要么被迫选择一个项目,要么输入自由格式文本。在后端,如果带有键'myvalue'的请求参数为空,那么您更愿意使用键'myautocomplete'查看请求参数。

答案 1 :(得分:1)

当我假设您设置了以下字段时:

<div>
    <input type="text" name="visible" class="autocomplete-reference" />
    <input type="hidden" name="hidden" />
</div>

你需要初始化js(它适用于jQuery 1.5.2):

$(document).ready(function() {
    $('.autocomplete-reference').each(function () {
        $(this).keydown(function(e){
            /*
            * this will reset hidden id reference on each visible field manual change
            * we have to bind it on keydown because we want to recognize event of submiting form by enter after autocomplete set
            */
            if (e.keyCode != 13) {
                $(this).siblings('input[type=hidden]').each(function () {
                    $(this).val('');
                });
            }
        });
        $(this).autocomplete({
            minLength: 1,
            /* you can set appending of autocomplete menu into some container to set css contextually
            appendTo: '#someElem',*/
            source: sourceFunction,
            search:function (event, ui) {
                //TODO ...spinner init...
            },
            open:function (event, ui) {
                /* you can grab autocomplete menu widget by this to manipulate some recognizing id, etc..
                 * $(this).autocomplete('widget')
                */
                //TODO ..stop spinner ...
                $(this).keydown(function(e){
                    /* this is important for live reference updates while arrow keys changes  */
                    if (e.keyCode == 37 || e.keyCode == 39) {
                       $($(this).data('autocomplete').menu.active).find('a').trigger('click');
                    }
                });
            },
            focus: function(event, ui) {
                /* here we'll map our data object onto both fields */
                $(this).val(ui.item.label);
                $(this).siblings('input[type=hidden]').each(function () {
                    $(this).val(ui.item.key);
                });
            },
            select: function(event, ui) {
                /* here we'll map our data object onto both fields */
                $(this).val(ui.item.label);
                $(this).siblings('input[type=hidden]').each(function () {
                    $(this).val(ui.item.key);
                });
            },
            close: function(event, ui) {
                //TODO ..stop spinner ...
            }
        });
    });
});

非常高兴有一些服务器端验证可以将exact:visible字段值转换为快速输入字符的引用。

答案 2 :(得分:0)

虽然这是一个老问题,但我的方法可以提供帮助。

.change事件中,您可以使用循环从源列表中搜索带有值的文本框值。

转到更多详细信息:这是在Ajax源列表中,但是锻炼类似。 Search a text In Jquery AutoComplete Ui

这件事让我困扰了很多次,最终我现在明白了:)

答案 3 :(得分:0)

您可以使用 event.preventDefault

通过ui.item.label或ui.item.value收集您选择的值并获取所需的值并将其设置为相同的文本框。

var idNameCombo = ui.item.label;
            event.preventDefault();
            $("#mID").val(idNameCombo.split(",")[0].trim());