11

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

我有以下要求:

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

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

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

最初我像这样设置自动完成小部件:

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

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

我在文本框下添加了一个隐藏字段并实现了 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 Autocomplete 文档列出了一个change事件,并声明参数的item属性ui将设置为所选项目。我想我可以在按键时重置隐藏的 id 字段,如果自动完成更改,则重新填充 ID。不幸的是,除了 keypress 事件捕获一大堆不应重置 ID的按键之外,return false上述select事件中管理文本框中文本所必需的语句会阻止change事件正确分配 ui.item。

所以现在我被困住了——我真的不知道我还能尝试什么让小部件支持默认情况下应该支持的功能。要么这个过程比它应该的要复杂得多,要么我错过了一些非常明显的东西。我已经挑选了所有可用的事件和所有示例,但空手而归。事实上,即使是 jQuery UI 页面上的“自定义数据和显示”示例也存在这个问题。

我可以在服务器端添加一些技巧来解决这个问题,但我真的更希望能够在客户端级别做到这一点。

我也更愿意坚持使用 jQuery UI 自动完成小部件,而不是切换到另一个小部件。

4

4 回答 4

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'的请求参数。

于 2010-07-27T13:43:31.643 回答
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 ...
            }
        });
    });
});

当然,有一些服务器端验证可以将精确的 :visible 字段值转换为快速输入人员的引用,这非常好。

于 2012-01-01T13:38:07.240 回答
0

您可以使用event.preventDefault

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

var idNameCombo = ui.item.label;
            event.preventDefault();
            $("#mID").val(idNameCombo.split(",")[0].trim());
于 2014-12-28T11:27:53.420 回答
0

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

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

转到更多详细信息:这里是 Ajax 源列表,但锻炼是相似的。 在 Jquery AutoComplete Ui 中搜索文本

这件事一直困扰着我很多次,现在我终于明白了:)

于 2012-12-07T07:04:46.247 回答