问题
I have next html structure
<select class="change_item_dropdown_ajax form-control" id="item_id" name="item_id" onchange="updateData(this, this.value, 16)" >
<optgroup label="System Data">
<option value="17">Test</option>
<option selected="selected" value="18">System</option>
</optgroup>
</select>
Javascript
$(".change_item_dropdown_ajax").select2({
ajax: {
url: "get_user_items",
dataType: 'json',
delay: 250,
theme: "classic",
data: function (params) {
return {
q: { name_contains: params.term } // search term
};
},
processResults: function (data) {
return {
results: data
};
},
cache: true
},
allowClear: true,
placeholder: '--- Please select item ---',
minimumInputLength: 1
});
I want to make possibility for customer to see some default system options with items <optgroup label="System Data">
, but also add ability to make search ajax queries by his own items.
However after binding select2 it doesn't show <optgroup label="System Data">...</optgroup>
,
select2 options are empty and it only displays hint "Please enter 1 or more characters".
It's not even clear if it is possible to do, thanks.
UPD Related to select2 removes default options when using ajax
Select-2 removes options when using ajax adapter.
UPD2 github issue https://github.com/select2/select2/issues/3828
回答1:
If you want to have an <optgroup>
which is always visible, regardless what the client searches for, and below that, in another <optgroup>
, you want to see the search results, try this out:
In your server side script, where you are processing the search query the client typed in, you should return a json_encoded array
with the items which you want to be displayed in the select box. Instead of this, try doing something like this:
** MODIFIED CODE PER YOUR REQUEST IN THE QUESTION COMMENT**
$q=$_REQUEST['q']; //the query string passed, note, that if you have minimumInputLength set, until that inputLength is reached, this part of the code won't run, so if you require the minimumInputLength, you should play with the templateResult option of select2
if (empty($q)) {
$results=array();
$result[0]=array(); //an optgroup to display when no query was sent
$result[0]['text']='System Data';
$result[0]['children']=array();
// populate your first optgroup here, using the format which you are sending to select2.
} else {
$result[0]=array(); //an optgroup for results for the users searches
$result[0]['text']='User results';
$result[0]['children']=array();
//populate the children array with the search related results
}
// json_encode the $result array, and return it
I am using a simmilar code, which works flawlesly at my side, but it is possible that some other things has to be set up before it will work(I wrote the code a few months ago, and I remember that I had a rather hard time figuring this out), if this approach doesn't work, notify me, and I will look into my code, to see how I did it exactly.
回答2:
Possible (and, unfortunately, I think the only) solution in this case is to write custom adapter. Something like this:
$.fn.select2.amd.define('select2/data/extended-ajax',['./ajax','../utils','jquery'], function(AjaxAdapter, Utils, $){
function ExtendedAjaxAdapter ($element,options) {
//we need explicitly process minimumInputLength value
//to decide should we use AjaxAdapter or return defaultResults,
//so it is impossible to use MinimumLength decorator here
this.minimumInputLength = options.get('minimumInputLength');
this.defaultResults = options.get('defaultResults');
ExtendedAjaxAdapter.__super__.constructor.call(this,$element,options);
}
Utils.Extend(ExtendedAjaxAdapter,AjaxAdapter);
//override original query function to support default results
var originQuery = AjaxAdapter.prototype.query;
ExtendedAjaxAdapter.prototype.query = function (params, callback) {
var defaultResults = (typeof this.defaultResults == 'function') ? this.defaultResults.call(this) : this.defaultResults;
if (defaultResults && defaultResults.length && (!params.term || params.term.length < this.minimumInputLength)){
var processedResults = this.processResults(defaultResults,params.term);
callback(processedResults);
}
else {
originQuery.call(this, params, callback);
}
};
return ExtendedAjaxAdapter;
});
https://gist.github.com/govorov/3ee75f54170735153349b0a430581195
This adapter first analyzes query term. AjaxAdapter will be kicked in if term is longer than minimumInputValue. Otherwise, defaultResults will be passed to the callback.
To use this adapter, just pass this to select2 options:
dataAdapter: $.fn.select2.amd.require('select2/data/extended-ajax')
I'm not using requireJS or AMD, if you do, use it to require adapter.
来源:https://stackoverflow.com/questions/33080739/select2-default-options-with-ajax