I have the following select on my page:
<select><option value="1" selected="selected">Caption</option></select>
I call select2 (v 4.0) init:
city.select2({
ajax: {
url: <...>,
data: <...>,
processResults: <...>,
cache: true
},
escapeMarkup: function(markup){ return markup; },
minimumInputLength: 0,
templateResult: function(repo){ return repo.name; },
templateSelection: function(repo){ return repo.name; }
});
The problem is that select2 is resetting default selected value and showing blank string. Is there any way to set default value on select2 init?
The issue was in your templateSelection method, as you are expecting a name property to be on your data object. Aside from the fact that text is now required and you wouldn't need the method if you re-mapped it, you aren't handling the case where the data object has a text property.
city.select2({
ajax: {
url: <...>,
data: <...>,
processResults: <...>,
cache: true
},
escapeMarkup: function(markup){ return markup; },
minimumInputLength: 0,
templateResult: function(repo){ return repo.name || repo.text; },
templateSelection: function(repo){ return repo.name || repo.text; }
});
This should fix your issue and display the initial selections properly.
The select2 docs now have an example of how to do this.
// Set up the Select2 control
$('#mySelect2').select2({
ajax: {
url: '/api/students'
}
});
// Fetch the preselected item, and add to the control
var studentSelect = $('#mySelect2');
$.ajax({
type: 'GET',
url: '/api/students/s/' + studentId
}).then(function (data) {
// create the option and append to Select2
var option = new Option(data.full_name, data.id, true, true);
studentSelect.append(option).trigger('change');
// manually trigger the `select2:select` event
studentSelect.trigger({
type: 'select2:select',
params: {
data: data
}
});
});
Basically, configure select2 for ajax and then pre-fill with the desired object. The magic is done in the last bit, .trigger() which causes select2 to pick up the change and render it.
Related
I have a dropdown created with select2 (v4.0.13 and I can not change it) using AJAX requests on a form where the user can search for things. The page is built with Thymeleaf and when the view is reloaded the dropdown value is lost.
Following the recommendation of the documentation itself when you deal with AJAX values, I have writed this code:
let selectedOption = $('#select2-id');
$.ajax({
type: 'GET',
dataType: 'json',
url: baseAjaxUrl + '/api_endpoint?q=' + myVar,
}).then(function (data) {
if (data.length !== 0) {
let optionValues = data[0];
let option = new Option(optionValues.name, optionValues.id, true, true);
selectedOption.append(option).trigger('change.select2');
selectedOption.trigger({
type: 'select2:select',
params: {data: optionValues}
});
}
});
Now, when the view is reloaded the dropdown has the value but does not show its text. An x appears to remove it and if you hover the mouse over it in the tooltip the text that should be displayed in the dropdown appears.
In the <span> generated by select2 I can see the title attribute with the value that should be displayed:
<span class="select2-selection__rendered" id="select2-anId-container" role="textbox" aria-readonly="true" title="The text that should be displayed">
<span class="select2-selection__clear" title="Remove all items" data-select2-id="20">×</span>
</span>
The select2 is initialised as follows:
$('#select2-id').select2({
ajax: {
url: baseAjaxUrl + '/api_endpoint',
dataType: 'json',
delay: 180,
data: function (parameters) {
return {
q: parameters.term,
page: parameters.page
};
},
processResults: function (data, page) {
return {
results: data
};
}
},
placeholder: {
id: "-1",
text: "Select an item"
},
allowClear: true,
escapeMarkup: function (markup) {
return markup;
},
minimumInputLength: 5,
templateResult: formatItem,
templateSelection: formatItemSelection,
theme: "bootstrap",
width: myCustomWidth
});
What is the problem or what have I done wrong?
Greetings.
After finding this answer, my problem was that when selecting an option, templateSelection is used. Checking the function I realised that the object I receive has the fields id and name. The object that handles select2 also has the fields id and name but it has another one, text, and this is the one it uses to show the value!
So in the function I use for templateSelection I have to do:
if (data.text === "") {
data.text = data.name;
}
... other stuff ...
return data.text;
Done!
I want to create a search input field using select2.js 4.0.5. I looked at the select2 example and basically, want to learn by recreating them without using the template result (only return text).
However, I cannot make it work. This is the closest I can get: myJSFiddle.
$(document).ready(function() {
$(".js-data-example-ajax").select2({
ajax: {
url: "https://api.github.com/search/repositories",
dataType: 'json',
delay: 250,
data: function(params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function(data, params) {
// parse the results into the format expected by Select2
// since we are using custom formatting functions we do not need to
// alter the remote JSON data, except to indicate that infinite
// scrolling can be used
params.page = params.page || 1;
return {
results: data.items,
pagination: {
more: (params.page * 30) < data.total_count
}
};
},
cache: true
}
});
});
Even copying directly everything from the example does not work: exampleJSFiddle.
I am still new to JS and Ajax. I'm sure that I'm missing something. Could someone please explain what am I missing?
I finally get it running. Although I don't know how to fix the size of the search box: (Working JSFiddle)
HTML
<select class="js-data-example-ajax"></select>
JS
$(".js-data-example-ajax").select2({
ajax: {
url: "https://api.github.com/search/repositories",
contentType: 'application/json',
dataType: 'json',
data: function(params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function(data) {
return {
results: data.items
};
},
cache: false
},
templateResult: formatResult
});
function formatResult(result) {
return result.full_name;
};
I've gotten xeditable and select2 to work with an api call as the source and everything works great EXCEPT the following.
After submitting the select2 dropdown, the value of the table is displayed as EMPTY and requires a page refresh in order to update to the correct value.
Does anyone know how to update the value to the selected select2 dropdown value?
my html:
<td class="eo_role"><a href="#" data-pk={{r.pk}} data-type="select2" data-url="/api/entry/{{r.pk}}/"
data-name="eo_role" data-title="Enter EO_role">{{r.eo_role}}</a></td>
here is my JS:
$('#example .eo_role a').editable( {
params: function(params) { //params already contain `name`, `value` and `pk`
var data = {};
data[params.name] = params.value;
return data;
},
source: 'http://localhost:8000/api/eo_role/select_two_data/',
tpl: '<select></select>',
ajaxOptions: {
type: 'put'
},
select2: {
cacheDatasource:true,
width: '150px',
id: function(pk) {
return pk.id;
},
ajax: {
url: 'http://localhost:8000/api/eo_role/select_two_data/',
dataType: "json",
type: 'GET',
processResults: function(item) {return item;}
}
},
formatSelection: function (item) {
return item.text;
},
formatResult: function (item) {
return item.text;
},
templateResult: function (item) {
return item.text;
},
templateSelection : function (item) {
return item.text;
},
});
Again - everything works (database updates, dropdownlist populates etc.) however the <td> gets updated with "EMPTY" after submitting the dropdown - requiring a page refresh to show the correct value.
I figured out a workaround. I'm SUPER PUMPED.
//outside of everything, EVERYTHING
//test object is a global holding object that is used to hold the selection dropdown lists
//in order to return the correct text.
var test = {};
$('#example .eo_role a').editable( {
params: function(params) { //params already contain `name`, `value` and `pk`
var data = {};
data[params.name] = params.value;
return data;
},
//MUST be there - it won't work otherwise.
tpl: '<select></select>',
ajaxOptions: {
type: 'put'
},
select2: {
width: '150px',
//tricking the code to think its in tags mode (it isn't)
tags:true,
//this is the actual function that triggers to send back the correct text.
formatSelection: function (item) {
//test is a global holding variable set during the ajax call of my results json.
//the item passed here is the ID of selected item. However you have to minus one due zero index array.
return test.results[parseInt(item)-1].text;
},
ajax: {
url: 'http://localhost:8000/api/eo_role/select_two_data/',
dataType: "json",
type: 'GET',
processResults: function(item) {
//Test is a global holding variable for reference later when formatting the selection.
//it gets modified everytime the dropdown is modified. aka super convenient.
test = item;
return item;}
}
},
});
I faced that same issue. I handle it that way:
In x-editable source code look for:
value2html: function(value, element) {
var text = '', data,
that = this;
if(this.options.select2.tags) { //in tags mode just assign value
data = value;
//data = $.fn.editableutils.itemsByValue(value, this.options.select2.tags, this.idFunc);
} else if(this.sourceData) {
data = $.fn.editableutils.itemsByValue(value, this.sourceData, this.idFunc);
} else {
//can not get list of possible values
//(e.g. autotext for select2 with ajax source)
}
As you can see, there is else statment, without any code (only 2 comments) that is the situation, with which we have a problem. My solution is to add missing code:
(...) else {
//can not get list of possible values
//(e.g. autotext for select2 with ajax source)
data = value;
}
That's fix problem without tags mode enabled. I do not detect any unwanted behaviors so far.
Example code:
jQuery('[data-edit-client]').editable({
type: 'select2',
mode: 'inline',
showbuttons: false,
tpl: '<select></select>',
ajaxOptions: {
type: 'POST'
},
select2: {
width: 200,
multiple: false,
placeholder: 'Wybierz klienta',
allowClear: false,
formatSelection: function (item) {
//test is a global holding variable set during the ajax call of my results json.
//the item passed here is the ID of selected item. However you have to minus one due zero index array.
return window.cacheData[parseInt(item)].text;
},
ajax: {
url: system.url + 'ajax/getProjectInfo/',
dataType: 'json',
delay: 250,
cache: false,
type: 'POST',
data: {
projectID: system.project_id,
action: 'getProjectClients',
customer: parseInt(jQuery("[data-edit-client]").attr("data-selected-company-id"))
},
processResults: function (response) {
window.cacheData = response.data.clients;
return {
results: response.data.clients
};
}
}
}
});
I'm loading multiple values into a Select2 element through Javascript, ajax and jquery. While the data is loading properly and can be accessed once loaded, I'm unable to set stored data in the Select2 element.
Edit: I'm using Select2 v3.5.
My code:
HTML:
<input class="jsData" style="width: 100%" id="select2Data"></input>
Javascript:
$(".jsData").select2({
ajax: {
minimumInputLength: 4,
contentType: 'application/json',
url: '<%=Url.Action("GetData","Controller")%>',
type: 'POST',
dataType: 'json',
data: function (term) {
return {
sSearchTerm: term
};
},
results: function (data) {
return {
results: $.map(JSON.parse(data), function (item) {
return {
text: item.term,
slug: item.slug,
id: item.Id
}
})
};
}
},
multiple: true
});
So, this creates a Select2 element where I can traverse to and from a database and load data depending on what I've typed. I can also access the data (entered by the user) using the following line:
$('.jsData').select2('val')
The above line returns an array, which I can store in the database. My current objective is to set the stored data back into the Select2 element. Any help in this matter would be most welcome.
Update: A relevant link for what I want to accomplish:
https://select2.github.io/examples.html#programmatic
I want the example of setting multiple elements in Select2. However, the difference would be in the fact that the example in the Select2 documentation brings data at the time of loading the page, while I will be making trips to fetch the data.
The Select2 v3.5.4 docs are a bit confusing around this. I think there's a typo in the docs that's misleading.
First, notice that when I retrieve the data from the remote source I'm returning it as an object in the format of {id: ##, name: NAME}.
The first step is to add the initSelection parameter and pass the function to retrieve the previously selected items.
The next step, where I believe there's a typo, is to define the formatSelection parameter (not the formatResult it states in the docs). This function defines how the previously selected result is displayed. In this case I'm merely showing the name property of the result.
The formatResult parameter defines how newly selected options are displayed. You'll notice formatResult and formatSelection are the same below. I could have reused a single function but felt this was better for demonstration.
$(document).ready(function() {
function formatResult(data) {
return data.name;
};
function formatSelection(data) {
return data.name;
}
$(".jsData").select2({
ajax: {
minimumInputLength: 4,
url: "https://jsonplaceholder.typicode.com/users",
type: "GET",
dataType: "json",
results: function(data) {
return {
results: $.map(data, function(user) {
return {
name: user.name,
id: user.id
};
})
};
}
},
initSelection: function(element, callback) {
var id = $(element).val();
if (id !== "") {
$.ajax("https://jsonplaceholder.typicode.com/users/" + id, {
dataType: "json"
}).done(function(data) {
callback(data);
});
}
},
formatResult: formatResult,
formatSelection: formatSelection,
multiple: true
});
});
Here's the full working example:
$(document).ready(function() {
function formatResult(data) {
return data.name;
};
function formatSelection(data) {
return data.name;
}
$(".jsData").select2({
ajax: {
minimumInputLength: 4,
url: "https://jsonplaceholder.typicode.com/users",
type: "GET",
dataType: "json",
results: function(data) {
return {
results: $.map(data, function(user) {
return {
name: user.name,
id: user.id
};
})
};
}
},
initSelection: function(element, callback) {
var id = $(element).val();
if (id !== "") {
$.ajax("https://jsonplaceholder.typicode.com/users/" + id, {
dataType: "json"
}).done(function(data) {
callback(data);
});
}
},
formatResult: formatResult,
formatSelection: formatSelection,
multiple: true
});
});
.jsData {
width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.4/select2.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.4/select2.css" rel="stylesheet"/>
<input class="jsData" style="width: 100%" id="select2Data" value="10"></input>
I'm using Select2 (ver 4.00) and loading remote data with ajax method.
I need to retrieve title of selected option, but in select2:select event data is undifined
my code:
$(".js-data-action-terms").select2({
ajax: {
url: ajaxurl + "?action=terms",
dataType: 'json',
data: function (params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function (data, page) {
return {
results: data.items
};
},
cache: false
},
escapeMarkup: function (markup) {
return markup;
},
minimumInputLength: 1,
templateResult: formatRepo,
templateSelection: formatRepoSelection
});
$('.js-data-action-terms').on("select2:select", function(e) {
console.log(e);
});
Result log:
In Select2 4.0.0, the selected object was moved from the evt.data property to evt.params.data. Now all extra data for events in Select2 is put in evt.params for consistency.