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

时间:2014-10-28 14:22:11

标签: javascript jquery ajax html5 html-datalist

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

HTML

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

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

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

更新

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

7 个答案:

答案 0 :(得分:3)

问题很长一段时间后我找到了IE和Chrome的解决方法(没有在Opera上测试过,而且已经可以用于Firefox了)。

解决方案是将输入集中在成功(或完成)功能结束时:

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

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

答案 1 :(得分:1)

如果您不在每个按键操作上发出AJAX请求,则可以消除此问题。您可以使用set/cleatTimeout尝试使用限制技术在最后一个字符键入后500ms后发出请求:

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

答案 2 :(得分:1)

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

减少DOM操作

通过这种改进,我每次成功回调时只会在DOM中插入一次。这减少了需要重新渲染的浏览器,并将有助于改善任何&#34; blips&#34;在视图中。

功能编程和较少惯用的jQuery

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

不是Hacky

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

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

答案 3 :(得分:0)

将#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');
    }
});
如果没有#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);
    }
});

答案 4 :(得分:0)

您的问题 是AJAX 异步

您实际上必须为您调用onSuccess的AJAX进行回调,然后更新数据列表。当然,那么你可能没有很好的表现/仍然有&#34;跳过&#34;行为,您的数据主义选项滞后。

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

答案 5 :(得分:0)

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

新值将在新输入事件出现后显示。

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

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

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

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

自动完成和输入功能可以解决我的问题,它也适用于Chrome。

答案 6 :(得分:0)

我找到了仅在GNOME Web(WebKit)上测试过的解决方案,该解决方案包括将输入元素的'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)