jQuery UI 自动完成与混合文本/ID 搜索

发布于 2024-09-10 18:28:21 字数 1651 浏览 1 评论 0原文

我在让 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 自动完成文档列出了一个 change 事件,并指出 ui 参数的 item 属性将设置为所选项目。我想我可以在按键时重置隐藏的 ID 字段,并在自动完成更改后重新填充 ID。不幸的是,除了按键事件捕获了一大堆不应该重置ID的按键之外,上面selectreturn false语句> 管理文本框中文本所需的事件会阻止 change 事件正确分配 ui.item。

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

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

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

I'm having a lot of trouble making jQuery's autocomplete widget work for me. I am using a list of key/value pairs from a server.

I have the following requirements:

If the user selects a value from the widget, I want to pass the ID to the server.

If the user doesn't select a value and enters raw text, or modifies a value that has already been selected, I want the ID field to be cleared and just the raw text to be sent to the server.

Assume that someAjaxFunction returns an array of objects that the autocomplete widget expects: {label:label, value:key}.

Initially I set the autocomplete widget up like so:

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

Changing the selection even by hovering over one of the items changes the text in the text box referenced by $(input) to the underlying key, rather than the label. This is highly undesirable from a user interaction point of view - indeed, the very reason why I am investigating this is because the users of the site I am building were consistently baffled by the text they entered seemingly turning into random numbers!

I added a hidden field under the text box and implemented the select() and focus() events in order to cloak the ID like so:

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

This works well when the user is sticking to the script provided by the autocomplete drop-down. The ID is cloaked and correctly submitted to the server. Unfortunately, if the user wants to enter some freeform text into the box and search based on that value, the ID field is not reset and the previously selected ID gets submitted to the server. This is also rather confusing.

The jQuery UI Autocomplete documentation lists a change event and states that the item property of the ui argument will be set to the selected item. I figured I could reset the hidden id field on a key press and re-populate the ID if the autocomplete is changed. Unfortunately, in addition to the keypress event capturing a whole bunch of keypresses that shouldn't reset the ID, the return false statement in the above select event which is necessary to manage the text in the text box prevents the change event from having ui.item properly assigned.

So now I'm stuck - I don't really know what else I can try to make the widget support functionality that it seems like it should support by default. Either this process is way more complicated than it should be, or I'm missing something really obvious. I've picked through all the available events and all the examples and come up empty handed. In fact, even the "Custom data and display" example on the jQuery UI page suffers from this problem.

I can add some hacks at the server side to cover for this, but I would really prefer to be able to do this at the client level.

I would also prefer to stick to the jQuery UI autocomplete widget rather than switch to another one.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

我乃一代侩神 2024-09-17 18:28:21

我执行自动完成的方式是创建一个包含输入的容器 div。当我选择一个元素时,我将包含跨度的链接添加到容器中,并隐藏输入框。

链接和跨度的样式使其看起来像一个带有 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”键的请求参数。

The way I'm doing autocomplete, is to create a container div that contains the input. When I select an element, I add a link containing a span to the container, and I hide the input box.

The link and span are styled so that it looks like a button, with an X, and has a click event handler to remove the entry from the DOM, clear the hidden field, and re-show the input box when clicked. So when an item is selected:

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

And when an item is not selected:

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

This way, you are either forced to select an item, or you enter free form text. On the backend, if the request parameter with key 'myvalue' is empty, then you would rather look at the request parameter with key 'myautocomplete'.

野の 2024-09-17 18:28:21

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

<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 字段值转换为引用,以便快速输入人员当然。

When i presume you have the following fields set:

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

You need to init following js (it works with 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 ...
            }
        });
    });
});

It's very nice to have some serverside validation which can convert exact :visible field values into references for quick typing folks of course.

永不分离 2024-09-17 18:28:21

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

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

转到了解更多详细信息:这里位于 Ajax 源列表中,但锻炼类似。
在 Jquery AutoComplete Ui 中搜索文本

这个东西有困扰了我很多次,现在我终于明白了:)

Though its an old question, my method can help.

On .change event you can search for the textbox value with the value in from your Source list using loop.

Goto for more details: Here it is in Ajax source list but workout is similar.
Search a text In Jquery AutoComplete Ui

This thing had been troubling me many times and eventually now i figured it out :)

莫言歌 2024-09-17 18:28:21

您可以使用 event.preventDefault

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

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

You can use event.preventDefault

Collect your selected values through ui.item.label or ui.item.value and get the needed value and set it to the same textbox.

var idNameCombo = ui.item.label;
            event.preventDefault();
            $("#mID").val(idNameCombo.split(",")[0].trim());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文