如何使用JavaScript刷新HTML5数据表?
我正在动态地将选项加载到HTML5 datalist
元素中。 但是,浏览datalist
在加载选项之前尝试显示datalist
。 这导致列表未被显示或者有时显示部分列表。 有没有办法在加载选项后通过JavaScript刷新列表?
HTML
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) { $("").html(ingredients[i].name).appendTo("#ingredients"); } // Trigger a refresh of the rendered datalist } }); });
注意:在Chrome和Opera中,仅当用户在输入文本后单击输入时,才会显示整个列表。 但是,我希望整个列表显示为用户类型。 Firefox不是问题,因为它似乎在更新选项时自动刷新列表。
UPDATE
我不确定这个问题是否有令人满意的答案,因为我认为这只是某些浏览器的缺点。 如果更新了datalist
列表,浏览器应刷新列表,但某些浏览器(包括Chrome和Opera)根本不这样做。 黑客?
相当长的一段时间后,我找到了IE和Chrome的解决方法(没有在Opera上测试过,已经可以用于Firefox了)。
解决方案是将输入集中在成功(或完成)function结束时:
$("#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) { $("").html(ingredients[i].name).appendTo("#ingredients"); } // Trigger a refresh of the rendered datalist // Workaround using focus() _this.focus(); } });
它适用于Firefox,Chrome和IE 11+(可能是10个)。
如果您不在每个键击中发出AJAX请求,则可以消除此问题。 您可以使用set/cleatTimeout
尝试使用限制技术在最后一个char类型后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++) { $("").html(ingredients[i].name).appendTo("#ingredients"); } } }); }, this), 500)); });
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插入一次。 这减少了需要重新渲染的浏览器,并有助于改善视图中的任何“昙花一现”。
function编程和较少惯用的jQuery
在这里,我们使用Array.prototype.map来清理一些jQuery并使事情变得不那么惯用。 您可以从ECMA图表中看到此function适用于您要定位的所有浏览器。
不是Hacky
这绝不是hacky。 IE似乎是唯一不会自动刷新输入以显示新列表选项的浏览器。 focus()只是一种确保输入重新聚焦的方法,它会强制刷新视图。
这个解决方案适用于我公司内部支持的所有浏览器,IE10 + Chrome和Firefox。
将#ingredients元素放在#container中并尝试以下代码:
$.ajax({ url: "/api/ingredients", data: {search: value.length > 0 ? value + "*" : ""}, success: function(ingredients) { $("#ingredients").remove(); var item = $(''); for (var i in ingredients) { item.append(""); } item.appendTo('#container'); } });
没有#container并使用jQuery replaceWith()会更好:
$.ajax({ url: "/api/ingredients", data: {search: value.length > 0 ? value + "*" : ""}, success: function(ingredients) { var item = $(''); for (var i in ingredients) { item.append(""); } $("#ingredients").replaceWith(item); } });
您的问题是AJAX是异步的 。
你实际上必须为你调用onSuccess
的AJAX进行回调 ,然后更新数据列表。 当然,那么你可能没有很好的表现/仍然有“跳过”行为,你的数据主义选项落后。
如果AJAX中的项目列表不是太大,您应该:1。使用第一个查询将ENTIRE列表加载到内存数组中,然后… 1.使用每次应用于数组的过滤函数有一个keyUp
事件。