use*_*192 29 html javascript jquery-select2
我正在开发一个使用Select2(版本3.5.1)的应用程序.设置此下拉/自动填充字段的HTML如下所示:
<input id="mySelect" class="form-control" type="hidden">
Run Code Online (Sandbox Code Playgroud)
form-control这个片段中的类来自Bootstrap.我正在使用以下代码从JavaScript初始化此字段:
function getItemFormat(item) {
var format = '<div>' + item.ItemName + '</div>';
return format;
}
$(function() {
$('#mySelect').select2({
minimumInputLength: 5,
placeholder: 'Search for an item',
allowClear: true,
ajax: {
url: '/api/getItems',
dataType: 'json',
quietMillis: 250,
data: function (term, page) {
return {
query: term
};
},
results: function (data, page) {
return { results: data, id: 'ItemId', text: 'ItemText' };
}
},
formatResult: getItemFormat,
dropdownCssClass: "bigdrop",
escapeMarkup: function (m) { return m; }
});
});
Run Code Online (Sandbox Code Playgroud)
当我的选择字段加载时,它会成功渲染.一旦我输入至少第五个字符,它就会成功从服务器中提取项目并将它们列为选项.但是,如果我尝试选择其中一个,则没有任何反应.下拉弹出窗口保持打开状态.在实际领域没有任何东西.JavaScript控制台中没有错误.它就像我没有点击任何东西.
此外,我注意到当我将鼠标放在某个项目上或尝试使用箭头键导航选项列表时,没有任何内容突出显示.
我究竟做错了什么?
吖奇说*_*HUō 48
默认情况下,results您返回的对象ajax.results应该是此结构中的数组[{id:1,text:"a"},{id:2,text:"b"}, ...].
results: function (data, page) {
var array = data.results; //depends on your JSON
return { results: array };
}
Run Code Online (Sandbox Code Playgroud)
在Select2.js中,它实际上表明:
* @param options.results a function(remoteData, pageNumber, query) that converts data returned form the remote request to the format expected by Select2.
* The expected format is an object containing the following keys:
* results array of objects that will be used as choices
* more (optional) boolean indicating whether there are more results available
* Example: {results:[{id:1, text:'Red'},{id:2, text:'Blue'}], more:true}
Run Code Online (Sandbox Code Playgroud)
阅读源代码,我们可以看到ajax.resultsAJAX成功调用:
success: function (data) {
// TODO - replace query.page with query so users have access to term, page, etc.
// added query as third paramter to keep backwards compatibility
var results = options.results(data, query.page, query);
query.callback(results);
}
Run Code Online (Sandbox Code Playgroud)
因此ajax.results,实际上只是一个函数,您可以[{id:a,text:"a"},{id:b,text:"b"}, ...]在将数据传递到之前将数据格式化为适当的结构(例如)query.callback:
callback: this.bind(function (data) {
// ignore a response if the select2 has been closed before it was received
if (!self.opened()) return;
self.opts.populateResults.call(this, results, data.results, {term: term, page: page, context:context});
self.postprocessResults(data, false, false);
if (data.more===true) {
more.detach().appendTo(results).html(self.opts.escapeMarkup(evaluate(self.opts.formatLoadMore, self.opts.element, page+1)));
window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10);
} else {
more.remove();
}
self.positionDropdown();
self.resultsPage = page;
self.context = data.context;
this.opts.element.trigger({ type: "select2-loaded", items: data });
})});
Run Code Online (Sandbox Code Playgroud)
什么query.callback最终做的是设置逻辑正确,这样,当你选择的项目,并触发一个一切工作正常.selectChoice.
selectChoice: function (choice) {
var selected = this.container.find(".select2-search-choice-focus");
if (selected.length && choice && choice[0] == selected[0]) {
} else {
if (selected.length) {
this.opts.element.trigger("choice-deselected", selected);
}
selected.removeClass("select2-search-choice-focus");
if (choice && choice.length) {
this.close();
choice.addClass("select2-search-choice-focus");
this.opts.element.trigger("choice-selected", choice);
}
}
}
Run Code Online (Sandbox Code Playgroud)
因此,如果存在一些错误配置(例如results,在正确的结构中)导致在调用.select2-search-choice-focus之前不将类添加到DOM元素.selectChoice,则会发生以下情况:
下拉弹出窗口保持打开状态.在实际领域没有任何东西.JavaScript控制台中没有错误.它就像我没有点击任何东西.
有很多解决方案.当然,其中一个是做一些数组键操作ajax.results.
results: function (data, page) {
//data = { results:[{ItemId:1,ItemText:"a"},{ItemId:2,ItemText:"b"}] };
var array = data.results;
var i = 0;
while(i < array.length){
array[i]["id"] = array[i]['ItemId'];
array[i]["text"] = array[i]['ItemText'];
delete array[i]["ItemId"];
delete array[i]["ItemText"];
i++;
}
return { results: array };
}
Run Code Online (Sandbox Code Playgroud)
但你可能会问:为什么id必须是"id"而文本在数组中是"text"?
[{id:1,text:"a"},{id:2,text:"b"}]
Run Code Online (Sandbox Code Playgroud)
相反,阵列可以在这个结构中吗?
[{ItemId:1,ItemText:"a"},{ItemId:2,ItemText:"b"}]
Run Code Online (Sandbox Code Playgroud)
答案是肯定的.您只需要用自己的函数覆盖id和text函数.
这里是原来的功能.selecte2在Select2.js:
id: function (e) { return e == undefined ? null : e.id; },
text: function (e) {
if (e && this.data && this.data.text) {
if ($.isFunction(this.data.text)) {
return this.data.text(e);
} else {
return e[this.data.text];
}
} else {
return e.text;
}
},
Run Code Online (Sandbox Code Playgroud)
要覆盖它们,只需在要传递给的对象中添加自己的函数.selecte2:
$('#mySelect').select2({
id: function (item) { return item.ItemId },
text: function (item) { return item.ItemText }
......
});
Run Code Online (Sandbox Code Playgroud)
但是,列表关闭后,所选项目的文本不会出现在字段中.
这意味着.selectChoice已成功执行.现在的问题在于.updateSelection.在源代码中:
updateSelection: function (data) {
var container=this.selection.find(".select2-chosen"), formatted, cssClass;
this.selection.data("select2-data", data);
container.empty();
if (data !== null) {
formatted=this.opts.formatSelection(data, container, this.opts.escapeMarkup);
}
if (formatted !== undefined) {
container.append(formatted);
}
cssClass=this.opts.formatSelectionCssClass(data, container);
if (cssClass !== undefined) {
container.addClass(cssClass);
}
this.selection.removeClass("select2-default");
if (this.opts.allowClear && this.getPlaceholder() !== undefined) {
this.container.addClass("select2-allowclear");
}
}
Run Code Online (Sandbox Code Playgroud)
从这里我们可以看到,在相应的文本字符串放入输入之前,它会调用formatSelection.
formatSelection: function (data, container, escapeMarkup) {
return data ? escapeMarkup(this.text(data)) : undefined;
},
Run Code Online (Sandbox Code Playgroud)
以前我认为this.text(data)可以通过text: funcion(item){ ... }参数来覆盖,但遗憾的是它不会那样工作.
因此,要在字段中正确呈现文本,您应该formatSelection通过执行覆盖
$('#mySelect').select2({
id: function (item) { return item.ItemId },
formatSelection: function (item) { return item.ItemText }
//......
});
Run Code Online (Sandbox Code Playgroud)
而不是试图覆盖text(应该具有相同的效果,但这种覆盖方式尚未在库中支持/实现)
$('#mySelect').select2({
id: function (item) { return item.ItemId },
text: function (item) { return item.ItemText } //this will not work.
//......
});
Run Code Online (Sandbox Code Playgroud)
您面临的问题是select2希望您的所有结果都具有id属性.如果它们不需要,则需要使用id从每个结果返回id 的函数进行初始化.
除非您满足其中一个,否则不允许您选择结果.所以在你的例子中:
function getItemFormat(item) {
var format = '<div>' + item.ItemName + '</div>';
return format;
}
$(function() {
$('#mySelect').select2({
minimumInputLength: 5,
placeholder: 'Search for an item',
allowClear: true,
id: function(item) { return item.ItemId; }, /* <-- ADDED FUNCTION */
ajax: {
url: '/api/getItems',
dataType: 'json',
quietMillis: 250,
data: function (term, page) {
return {
query: term
};
},
results: function (data, page) {
return { results: data, id: 'ItemId', text: 'ItemText' };
}
},
formatResult: getItemFormat,
dropdownCssClass: "bigdrop",
escapeMarkup: function (m) { return m; }
});
});
Run Code Online (Sandbox Code Playgroud)