如何使用 JavaScript 刷新 HTML5 数据列表?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26610752/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 06:12:45  来源:igfitidea点击:

How do you refresh an HTML5 datalist using JavaScript?

javascriptjqueryajaxhtmlhtml-datalist

提问by David Jones

I'm loading options into an HTML5 datalistelement dynamically. However, the browser attempts to show the datalistbefore the options have loaded. This results in the list not being shown or sometimes a partial list being shown. Is there any way to refresh the list via JavaScript once the options have loaded?

我正在将选项datalist动态加载到 HTML5元素中。但是,浏览器会尝试datalist在选项加载之前显示。这会导致列表未显示或有时显示部分列表。选项加​​载后,有没有办法通过 JavaScript 刷新列表?

HTML

HTML

<input type="text" id="ingredient" list="ingredients">
<datalist id="ingredients"></datalist>

JavaScript

JavaScript

$("#ingredient").on("keyup", function(event) {
    var value = $(this).val();
    $.ajax({
        url: "/api/ingredients",
        data: {search: value.length > 0 ? value + "*" : ""},
        success: function(ingredients) {
            $("#ingredients").empty();
            for (var i in ingredients) {
                $("<option/>").html(ingredients[i].name).appendTo("#ingredients");
            }
            // Trigger a refresh of the rendered datalist
        }
    });
});

Note: In Chrome and Opera, the entire list is only shown if the user clicks on the input after entering text. However, I'd like the entire list to appear asthe user types. Firefox is not a problem, as it appears to refresh the list automatically when the options are updated.

注意:在 Chrome 和 Opera 中,只有当用户在输入文本后单击输入时才会显示整个列表。但是,我希望整个列表显示用户键入。Firefox 没有问题,因为它似乎会在选项更新时自动刷新列表。

UPDATE

更新

I'm not sure this question has a satisfactory answer, as I believe this is simply a shortcoming of certain browsers. If a datalistis updated, the browser shouldrefresh the list, but some browsers (including Chrome and Opera) simply do not do this. Hacks?

我不确定这个问题有一个令人满意的答案,因为我认为这只是某些浏览器的一个缺点。如果 adatalist被更新,浏览器应该刷新列表,但一些浏览器(包括 Chrome 和 Opera)根本不这样做。黑客?

回答by Yoyo

Quite a long time after question but I found a workaround for IE and Chrome (not tested on Opera and already OK for Firefox).

很长一段时间后,我找到了一个适用于 IE 和 Chrome 的解决方法(未在 Opera 上测试,但对于 Firefox 已经可以了)。

The solution is to focus the input at the end of success (or done) function like this :

解决方案是在成功(或完成)功能结束时关注输入,如下所示:

$("#ingredient").on("keyup", function(event) {
var _this = $(this);
var value = _this.val();
$.ajax({
    url: "/api/ingredients",
    data: { search: value.length > 0 ? value + "*" : "" },
    success: function(ingredients) {
        $("#ingredients").empty();
        for (var i in ingredients) {
           $("<option/>").html(ingredients[i].name).appendTo("#ingredients");
        }
        // Trigger a refresh of the rendered datalist
        // Workaround using focus()
        _this.focus();
    }
});

It works on Firefox, Chrome and IE 11+ (perhaps 10).

它适用于 Firefox、Chrome 和 IE 11+(可能是 10)。

回答by Josh Hardy

Yoyogave the correct solution, but here's a better way to structure your inserts into the DOM.

Yoyo提供了正确的解决方案,但这里有一种更好的方法来将插入内容构建到 DOM 中。

$("#ingredient").on("keyup", function(event) {
var _this = $(this);
var value = _this.val();
$.ajax({
    url: "/api/ingredients",
    data: { search: value.length > 0 ? value + "*" : "" },
    success: function(ingredients) {
        var options = ingredients.map(function(ingredient) {
          var option = document.createElement('option');
          option.value = ingredient.name;
          return option;
        });
        $("#ingredients")
          .empty()
          .append(options);
        // Trigger a refresh of the rendered datalist
        // Workaround using focus()
        _this.focus();
    }
});

Less DOM manipulation

更少的 DOM 操作

With this refinement, I'm only inserting into the DOM a single time per each successful callback. This cuts down on the browser needing to re-render, and will help improve any "blips" in the view.

通过这种改进,我只在每次成功回调时向 DOM 插入一次。这减少了需要重新渲染的浏览器,并有助于改善视图中的任何“光点”。

Functional Programming and Less Idiomatic jQuery

函数式编程和不太惯用的 jQuery

Here we are using the Array.prototype.mapto clean up some of the jQuery and make things a bit less idiomatic. You can see from the ECMA Chartthat this function will work in all browsers you are targeting.

这里我们使用Array.prototype.map来清理一些 jQuery 并让事情变得不那么惯用了。您可以从ECMA 图表中看到,此功能适用于您定位的所有浏览器。

Not Hacky

不是黑客

This by no means is hacky. IE appears to be the only browser that doesn't automatically refresh the input to display the new list options. focus() is just a way to ensure the input is refocused which forces a refresh of the view.

这绝不是hacky。IE 似乎是唯一不会自动刷新输入以显示新列表选项的浏览器。focus() 只是确保输入重新聚焦的一种方法,这会强制刷新视图。

This solution works very well in all of the browsers that my company has to support internally, IE10+ Chrome and Firefox.

该解决方案适用于我公司必须在内部支持的所有浏览器,IE10+ Chrome 和 Firefox。

回答by dfsq

You can probably eliminate the problem if you don't make AJAX request on every key stroke. You can try throttle technique using set/cleatTimeoutto issue request after 500ms after the last char typed:

如果您不在每次击键时都发出 AJAX 请求,您可能可以消除该问题。您可以尝试使用油门技术set/cleatTimeout在输入最后一个字符后 500 毫秒后发出请求:

$("#ingredient").on("keyup", function(event) {

    clearTimeout($(this).data('timeout'));

    $(this).data('timeout', setTimeout($.proxy(function() {

        var value = $(this).val();

        $.ajax({
            url: "/api/ingredients",
            data: {search: value.length > 0 ? value + "*" : ""},
            success: function(ingredients) {
                $("#ingredients").empty();
                for (var i = 0; i < ingredients.length; i++) {
                    $("<option/>").html(ingredients[i].name).appendTo("#ingredients");
                }
            }
        });

    }, this), 500));
});

回答by Flak DiNenno

Your issueis that the AJAX is asynchronous.

您的问题是 AJAX 是异步的

You'd actually have to have a callbackfor the AJAX which you call onSuccesswhich would then update the datalist. Of course, then you might not have great performance/still have a "skipping" behavior, where your datalist options are lagging behind.

你实际上必须有一个你调用的 AJAX回调onSuccess然后它会更新数据列表。当然,那么你可能没有很好的性能/仍然有“跳过”行为,你的数据列表选项落后了。

If your list of items from the AJAX isn't too large, you should: 1. load the ENTIRE list into memory array with the first query, then... 1. use a filtering function that is applied to the array each time you have a keyUpevent.

如果您的 AJAX 项目列表不是太大,您应该: 1. 使用第一个查询将整个列表加载到内存数组中,然后... 1. 使用过滤功能,每次您都应用到该数组有一个keyUp活动。

回答by Ragnar

Place your #ingredients element is inside #container and try this code:

将您的 #ingredients 元素放在 #container 内并尝试以下代码:

$.ajax({
    url: "/api/ingredients",
    data: {search: value.length > 0 ? value + "*" : ""},
    success: function(ingredients) {
        $("#ingredients").remove();
        var item = $('<datalist id="ingredients"></datalist>');
        for (var i in ingredients) {                
            item.append("<option>"+ ingredients[i].name +"</option>");
        }
        item.appendTo('#container');
    }
});

even better without #container and using jQuery replaceWith():

没有 #container 和使用 jQuery replaceWith() 甚至更好:

$.ajax({
    url: "/api/ingredients",
    data: {search: value.length > 0 ? value + "*" : ""},
    success: function(ingredients) {
        var item = $('<datalist id="ingredients"></datalist>');
        for (var i in ingredients) {                
            item.append("<option>"+ ingredients[i].name +"</option>");
        }
        $("#ingredients").replaceWith(item);
    }
});

回答by alessandro

I had the same problem when updating datalist.

更新数据列表时我遇到了同样的问题。

The new values would not show until new input event.

直到新的输入事件才会显示新值。

I tried every suggested solutions but nothing using Firefox and updating datalist via AJAX.

我尝试了所有建议的解决方案,但没有使用 Firefox 并通过 AJAX 更新数据列表。

However, I solved the problem (for simplicity, I'll use your example):

但是,我解决了这个问题(为简单起见,我将使用您的示例):

<input type="text" id="ingredient" list="ingredients" **autocomplete="off"**>
<datalist id="ingredients"></datalist>

$("#ingredient").on("**input**", function(event) { ....}

Autocomplete and input is the couple that solve my problems and it works with Chrome too.

自动完成和输入是解决我问题的一对,它也适用于 Chrome。

回答by Andres

I found a solution tested only on GNOME Web (WebKit) that consist on set the 'list' attribute of the input element to empty string and, inmediately after, set it again with the id of the datalist element. Here is the example, supose that your input element is stored in a variable named input_element:

我找到了一个仅在 GNOME Web (WebKit) 上测试的解决方案,它包括将 input 元素的“list”属性设置为空字符串,然后立即使用 datalist 元素的 id 再次设置它。这是示例,假设您的输入元素存储在名为 的变量中input_element

var datalist = document.getElementById(input_element.list.id);
// at this point input_element.list.id is equals to datalist.id
// ... update datalist element here
// And now the trick:
input_element.setAttribute('list','')
input_element.setAttribute('list',datalist.id)