我正在动态地将选项加载到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)根本不这样做。黑客?
答案 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中插入一次。这减少了需要重新渲染的浏览器,并将有助于改善任何&#34; blips&#34;在视图中。
这里我们使用Array.prototype.map来清理一些jQuery并使事情变得不那么惯用。您可以在ECMA Chart中看到此功能适用于您定位的所有浏览器。
这绝不是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)