我正在将<input type="hidden">
转换为select2下拉列表并通过查询方法提供数据
$('#inputhidden').select2({
query: function( query ) {
query.callback( data ); // the data is in the format select2 expects and all works well..
);
});
问题是我需要破解select2用户界面并在搜索栏顶部放置两个按钮,单击这些按钮将执行ajax调用,并且必须更新select2内容。
现在,我需要完成这些更新,而不是完全重建select2,而只是刷新下拉列表中的项目。我找不到将一组新数据传递给已创建的select2控件的方法,这可能吗?
答案 0 :(得分:43)
如果你有带有选项的本地数组(由ajax调用接收),我认为你应该使用data
参数作为返回选择框结果的函数:
var pills = [{id:0, text: "red"}, {id:1, text: "blue"}];
$('#selectpill').select2({
placeholder: "Select a pill",
data: function() { return {results: pills}; }
});
$('#uppercase').click(function() {
$.each(pills, function(idx, val) {
pills[idx].text = val.text.toUpperCase();
});
});
$('#newresults').click(function() {
pills = [{id:0, text: "white"}, {id:1, text: "black"}];
});
FIDDLE : http://jsfiddle.net/RVnfn/576/
如果您使用按钮自定义select2界面,只需调用updateResults
(此方法不允许从select2对象的外部调用,但如果需要,可以将其添加到select2中的allowedMethods
数组中更新数据数组后的方法(例子中的例子)。
带有附加updateOptions
的自定义数据适配器(不清楚为什么原始ArrayAdapter
缺少此功能)可用于动态更新选项列表(此示例中的所有选项):
$.fn.select2.amd.define('select2/data/customAdapter',
['select2/data/array', 'select2/utils'],
function (ArrayAdapter, Utils) {
function CustomDataAdapter ($element, options) {
CustomDataAdapter.__super__.constructor.call(this, $element, options);
}
Utils.Extend(CustomDataAdapter, ArrayAdapter);
CustomDataAdapter.prototype.updateOptions = function (data) {
this.$element.find('option').remove(); // remove all options
this.addOptions(this.convertToOptions(data));
}
return CustomDataAdapter;
}
);
var customAdapter = $.fn.select2.amd.require('select2/data/customAdapter');
var sel = $('select').select2({
dataAdapter: customAdapter,
data: pills
});
$('#uppercase').click(function() {
$.each(pills, function(idx, val) {
pills[idx].text = val.text.toUpperCase();
});
sel.data('select2').dataAdapter.updateOptions(pills);
});
FIDDLE : https://jsfiddle.net/xu48n36c/1/
在v4中,您可以定义可以使用本地数据数组的自定义传输方法(例如,@xaleb_Kiage,我已经使用它而没有成功)
docs:https://select2.github.io/options.html#can-an-ajax-plugin-other-than-jqueryajax-be-used
Select2使用ajax.transport中定义的传输方法发送 对您的API的请求。默认情况下,此传输方法是jQuery.ajax 但这可以改变。
$('select').select2({
ajax: {
transport: function(params, success, failure) {
var items = pills;
// fitering if params.data.q available
if (params.data && params.data.q) {
items = items.filter(function(item) {
return new RegExp(params.data.q).test(item.text);
});
}
var promise = new Promise(function(resolve, reject) {
resolve({results: items});
});
promise.then(success);
promise.catch(failure);
}
}
});
使用此方法但是如果数组中的选项文本发生更改,则需要更改选项的ID - 内部select2 dom选项元素列表未修改。如果数组中的选项id保持不变 - 将显示以前保存的选项而不是从数组更新!如果仅通过向其添加新项目来修改数组,那就不是问题了 - 对于大多数常见情况都可以。
FIDDLE: https://jsfiddle.net/xu48n36c/3/
答案 1 :(得分:17)
我认为直接交付数据就足够了:
$("#inputhidden").select2("data", data, true);
请注意,第二个参数似乎表示需要刷新。
感谢@Bergi寻求this的帮助。
如果没有自动更新,您可以尝试直接调用它的updateResults方法。
$("#inputhidden").select2("updateResults");
或者通过向“input.select2-input”发送触发器来间接触发它,如下所示:
var search = $("#inputhidden input.select2-input");
search.trigger("input");
答案 2 :(得分:12)
将Select2 4.0与Meteor一起使用,您可以执行以下操作:
Template.TemplateName.rendered = ->
$("#select2-el").select2({
data : Session.get("select2Data")
})
@autorun ->
# Clear the existing list options.
$("#select2-el").select2().empty()
# Re-create with new options.
$("#select2-el").select2({
data : Session.get("select2Data")
})
发生了什么:
这适用于任何被动数据源 - 例如Collection.find()。fetch() - 而不仅仅是Session.get()。
注意:从Select2版本4.0开始,您必须在添加新的onces之前删除现有选项。 See this GitHub Issue for details。在没有清除现有选项的情况下,没有“更新选项”的方法。
以上是coffeescript。与Javascript非常相似。
答案 3 :(得分:3)
我通过使用ajax选项并指定自定义传输函数来解决此问题。
看到这个小提琴Select2 dynamic options demo
以下是使其发挥作用的相关问题。
var $items = [];
let options = {
ajax: {
transport: function(params, success, failure) {
let items = $items;
if (params.data && params.data.q) {
items = items.filter(function(item) {
return new RegExp(params.data.q).test(item.text);
});
}
let promise = new Promise(function(resolve, reject) {
resolve({
results: items
});
});
promise.then(success);
promise.catch(failure);
}
},
placeholder: 'Select item'
};
$('select').select2(options);
let count = $items.length + 1;
$('button').on('click', function() {
$items.push({
id: count,
text: 'Item' + count
});
count++;
});
答案 4 :(得分:2)
var selBoxObj = $('#selectpill'); selBoxObj.trigger( “change.select2”);
答案 5 :(得分:1)
据我所知,如果不刷新整个列表或输入一些搜索文本并使用查询功能,就无法更新select2选项。
那些按钮应该做什么?如果它们用于确定选择选项,为什么不将它们放在选择框之外,并让它们以编程方式设置选择框数据然后打开它?我不明白你为什么要把它们放在搜索框的顶部。如果用户不应该搜索,您可以使用minimumResultsForSearch选项隐藏搜索功能。
修改:这个怎么样......
<强> HTML 强>:
<input type="hidden" id="select2" class="select" />
<强>的Javascript 强>
var data = [{id: 0, text: "Zero"}],
select = $('#select2');
select.select2({
query: function(query) {
query.callback({results: data});
},
width: '150px'
});
console.log('Opening select2...');
select.select2('open');
setTimeout(function() {
console.log('Updating data...');
data = [{id: 1, text: 'One'}];
}, 1500);
setTimeout(function() {
console.log('Fake keyup-change...');
select.data().select2.search.trigger('keyup-change');
}, 3000);
示例:Plunker
编辑2:这至少会让它更新列表,但如果您在触发keyup-change
事件之前输入了搜索文本,仍然会有一些奇怪。
答案 6 :(得分:1)
对于Select2 4.X
var instance = $('#select2Container').data('select2');
var searchVal = instance.dropdown.$search.val();
instance.trigger('query', {term:searchVal});
答案 7 :(得分:0)
尝试一下:
var data = [{id: 1, text: 'First'}, {id: 2, text: 'Second'}, {...}];
$('select[name="my_select"]').empty().select2({
data: data
});
答案 8 :(得分:0)
answer given by SpinyMan很重要,因为empty()
方法将删除select2实例,因此不再保留任何自定义选项。如果要保留现有的select2选项,则必须保存它们,销毁现有的select2实例,然后重新初始化。您可以这样做:
const options = JSON.parse(JSON.stringify(
$('#inputhidden').data('select2').options.options
));
options.data = data;
$('#inputhidden').empty().select2('destroy').select2(options);
我建议始终始终显式传递select2选项,因为以上内容仅复制了简单选项,而不复制任何自定义回调或适配器。另请注意,这需要select2(本文发布时为4.0.13)的最新稳定版本。
我编写了通用函数来处理一些功能:
function select2UpdateOptions(
selector,
data,
newOptions = null,
keepExistingSelected = true
) {
// loop through all instances of the matching selector and update each instance
$(selector).each(function() {
select2InstanceUpdateOptions($(this), data, newOptions, keepExistingSelected);
});
}
// update an existing select2 instance with new data options
function select2InstanceUpdateOptions(
instance,
data,
newOptions = null,
keepSelected = true
) {
// make sure this instance has select2 initialized
// @link https://select2.org/programmatic-control/methods#checking-if-the-plugin-is-initialized
if (!instance.hasClass('select2-hidden-accessible')) {
return;
}
// get the currently selected options
const existingSelected = instance.val();
// by default use the existing options of the select2 instance unless overridden
// this will not copy over any callbacks or custom adapters however
const options = (newOptions)
? newOptions
: JSON.parse(JSON.stringify(instance.data('select2').options.options))
;
// set the new data options that will be used
options.data = data;
// empty the select and destroy the existing select2 instance
// then re-initialize the select2 instance with the given options and data
instance.empty().select2('destroy').select2(options);
// by default keep options that were already selected;
// any that are now invalid will automatically be cleared
if (keepSelected) {
instance.val(existingSelected).trigger('change');
}
}