我有一些链接到远程数据的Kendo AutoComplete字段(数百种可能性,因此DropDownList不是一个选项)。
如何强制用户从显示的列表中进行选择?
我还要检索从数据源返回的其他数据,例如
$("#station").kendoAutoComplete({
dataSource: stationData,
minLength: 2,
dataTextField: 'name',
select: function(e){
var dataItem = this.dataItem(e.item.index());
console.dir(dataItem);
}
});
我正在使用dataItem
中的数据做其他事情,它需要是一个有效的选择。
谢谢
解决:我想我可能过于复杂了。答案很简单,发布在下面。
var valid;
$("#staton").kendoAutoComplete({
minLength: 2,
dataTextField: "name",
open: function(e) {
valid = false;
},
select: function(e){
valid = true;
},
close: function(e){
// if no valid selection - clear input
if (!valid) this.value('');
},
dataSource: datasource
});
如果列表未打开,此方法允许用户在AutoComplete中键入他们喜欢的内容。有两个更正来解决这个问题:
...
change: function(e){ if (!valid) this.value(''); }
也许,您可以使用blur
事件进行自己的验证:
$("#station").blur(function() {
var data = stationData,
nbData = data.length,
found = false;
for(var iData = 0; iData < nbData; iData++) {
if(this.value === data[iData].yourfieldname) // replace "yourfieldname" by the corresponding one if needed
found = true;
}
console.log(found);
});
你可以检查this fiddle。
除了@ Rock'n'muse提出的答案之外,OP发布的答案肯定是好的主张,但两者都错过了重要且理想的功能方面。
当使用@Mat给出的解决方案并实现@ Rock'n'muse的change
-vice-close
建议时,如果没有从过滤后的数据源中进行选择,则输入的值确实会从小部件中清除。这很棒;但是,如果用户输入有效内容并从筛选列表中选择一个值,则将光标放在值的末尾并键入现在使值无效的内容(不返回数据源中的任何有效选择),未从窗口小部件清除键入的值。
发生的事情是,如果先前输入的(和有效的)值应该改变,isValid
值仍然是true
。解决方案是在触发过滤事件后立即将isValid
设置为false
。当用户更改键入的值时,窗口小部件会尝试过滤数据源以搜索键入的值。一旦isValid
事件被触发,将false
设置为filter
就可以确保change
事件的“干净状态”,如@ Rock'n'muse的解决方案所示。
因为我们在触发isValid
事件时将filtering
设置为false,所以我们不需要在open
事件中这样做(因为数据源过滤必须在用户看到选项之前发生)。因此,从@ Mat的解决方案中删除了open
事件绑定。这也意味着在宣布false
时isValid
的初始分配是多余的,但在声明时的变量赋值总是一个好主意。
以下是来自@Mat的解决方案以及@ Rock'n'muse的建议以及应用的filtering
实现:
var isValid = false;
$("#staton").kendoAutoComplete({
minLength: 2,
dataTextField: "name",
select: function () {
valid = true;
},
change: function (e) {
// if no valid selection - clear input
if (!valid) {
e.sender.value("");
}
},
filtering: function () {
valid = false;
},
dataSource: datasource
});
作为附录,使用select
事件绑定来设置和评估一个简单的布尔值@Mat建议比在数据源上使用jQuery $.each(...)
更清晰,更简单和更快,以确保输入的值与实际值匹配change
事件中的数据源项。在我从@Mat(本页)找到解决方案之前,这是我第一次想到解决方案,这就是我对他的解决方案及其问题进行投票的理由。
您很可能需要一些自定义逻辑,在超过两个符号的最小长度后拦截每个键击,并阻止该选项输入使用户字符串与自动完成列表中的任何项不匹配的字符。
为此目的,拦截Kendo自动完成的更改事件,并将来自用户的当前输入值与已过滤列表中的项目进行比较。
希望这可以帮助,
$("#autocomplete_id").val("");
$("#autocomplete").kendoAutoComplete({
dataSource: datasource,
minLength: 1,
dataTextField: "catname",
dataValueField:"id",
select: function(e) {
var dataItem = this.dataItem(e.item.index());
$("#autocomplete_id").val(dataItem.id);
},
dataBound: function(e){
$("#autocomplete_id").val("");
}
});
仅供参考,autocomplete_id是一个隐藏字段,用于存储自动填充的值。 - 有时,我们希望dataWalueField不是dataTextField。因此,它有助于实现其目的。
在此,您可以从元素autocomplete_id获取自动完成“id”的值 - 这是来自serverside的dataValueField。
在数据绑定中,其值设置为null,而在选择时,它被赋予“id”值。
虽然accepted answer有效,但它不是最好的解决方案。
如果用户在kendo AutoComplete小部件触发open事件之前输入值,则所提供的解决方案不会考虑。结果,输入的值不是强制的,因此输入/选择无效。
我的方法假设应用程序在MVC中运行,并且数组在ViewData中传递。但这可以根据您的环境进行更改。
我的方法:
var validSelect, isSelected;
$("#staton").kendoAutoComplete({
minLength: 2,
filter: "startswith",
dataTextField: "name",
filtering: function(e) {
validSelect = false;
dataArr = @Html.Raw(Json.Encode(ViewData["allStatons"]));
// for loop within the ViewData array to find for matching ID
for (var i = 0; i < dataArr .length; i++){
if (dataArr[i].ID.toString().match("^" + $("#staton").val())) {
validSelect = true;
break;
}
}
// if value entered was not found in array - clear input
if (!validSelect) $("#staton").val("");
},
select: function(e){
isSelected = true;
},
close: function(e){
// if selection is invalid or not selected from the list - clear input
if (!validSelect || !isSelected) $("#staton").val("");
},
dataSource: datasource
});
如您所见,此方法需要加载服务器端的数组,以便在窗口小部件的过滤事件期间匹配。
我只是使用更改事件在Telerik的网站上找到了这个。对我来说这个效果最好。我添加了“值===''”检查。当用户“清除”选择时,这将捕获。
Here's the link to the full article.
$("#countries").kendoAutoComplete({
dataSource: data,
filter: "startswith",
placeholder: "Select country...",
change: function() {
var value = this.value();
if (value === '') return;
var found = false;
var data = this.dataSource.view();
for(var idx = 0, length = data.length; idx < length; idx++) {
if (data[idx] === value) {
found = true;
break;
}
}
if (!found) {
this.value("");
alert("Custom values are not allowed");
}
}
});
在我的自动完成更改事件中,我检查所选项目,如果未选中则清除单元格。
function myAutoComplete_OnChange(e)
{
if (this.dataItem())
{
// Don't use filtered value as display, instead use this value.
e.sender.element[0].value = this.dataItem().WidgetNumber;
}
else
{
var grid = $("#grid").data("kendoGrid");
grid.dataItems()[grid.select().index()].WidgetKey = null;
grid.dataItems()[grid.select().index()].WidgetNumber = null;
}
}