I am using jquery-select2-4 to search an external database and present the user with search results that he can choose from.
I have a working version running on this jsfiddle.
But if, for example, only 1 search result is returned I want to skip the whole selection process, and just add the returned search result to the list of selected options. According to the select2 docs I can add a new option like this:
option = new Option("Sample text", "123", true, true);
select2_element.append(option);
select2_element.trigger('change');
This seems to work to some extent. But there are a few problems.
id
and a text
.undefined
.I realize that this question contains 3 facets, but all 3 facets probably refers back to this 1 question:
How do you programmatically add a new jquery-select2-4 option and reset the search field?
For your reference, this is the context of the code I'm asking about:
var formatRepo, formatRepoSelection, selectRepos;
formatRepoSelection = function(element) {
return element.name + ' ' + element.forks + ' ' + element.id;
};
formatRepo = function(element) {
var markup;
if (!element.loading) {
return markup = element.name + ' ' + element.id;
}
};
selectRepos = function() {
var option, select2_element;
select2_element = $('#select2_element');
select2_element.select2({
ajax: {
url: "https://api.github.com/search/repositories",
dataType: 'json',
data: function (params) {
return {
q: params.term,
page: params.page
};
},
processResults: function (data, params) {
if (data.items.length === 1) {
// START: The code I am asking about.
// Add the search result directly as an option.
option = new Option("Sample text", "123", true, true);
select2_element.append(option);
return select2_element.trigger('change');
// END: The code I am asking about.
} else {
params.page = params.page || 1;
return {
results: data.items,
pagination: {
more: (params.page * 30) < data.total_count
}
};
}
},
cache: true
},
escapeMarkup: function(markup) {
return markup;
},
templateResult: formatRepo,
templateSelection: formatRepoSelection
});
};
$(function() {
return selectRepos();
});
I made two changes to the original code:
As you indicated, the creation of an option
element has its limitations: you can only specify the id and text properties, leaving no possibility to have access to the selected item's other properties.
Also, it generates undefined values. This is because the callback function formatRepoSelection tries to access properties (name and forks) that are undefined for the object created for the option
element. You could have tried to work around this and use the text property in that case, but still you would have no solution for the above limitations.
The solution I suggest here has a different approach. Instead of creating the tag directly, you could simulate the user's selection of that last item, sending a mouseup event to that list item.
This has as immediate advantage that the normal selection behaviour is applied as if the user had clicked the item, and so it solves immediately all three issues you had:
Here is the code implementing this:
if (data.items.length === 1) {
// Change 1:
// Allow the list to update
setTimeout(function() {
// ... and then send a click event to the first list item
// Note the used id has the SELECT id in the middle.
$("#select2-select2_element-results li:first-child").trigger('mouseup');
}, 0);
The disadvantage of this solution is that you make yourself dependent on an implementation aspect; a future version of select2 may organise the results differently in terms of HTML elements and properties.
But it should not be a big deal to update the code whenever you decide to go with a newer version of select2.
Your code generated an error in the select2 library:
TypeError: b is undefined, at select2.min.js:2:9842
This is because of this statement:
return select2_element.trigger('change');
This returns the jQuery select2_element object, but library expects the return value to have a results property.
As that trigger is not needed any more, this can be fixed by replacing the above with:
// Change 2:
// Return empty results array
return {
results: data.items
};
Don't be tempted to set results: []
, because we still need the item to be there to simulate the mouse event with.
And... that is all.
Here is the working solution: JS fiddle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With