I'm trying setup data attributes into select2 options but without success, at this moment i have the following JS code
_properties.$localElement.select2({
ajax: {
url: "url",
type: "POST",
dataType: 'json',
delay: 250,
data: function (params) {
return {
name: params.term, // search term
type: 1
};
},
processResults: function (data) {
return {
results: $.map(data, function (item) {
return {
text: item.name,
source: item.source,
id: item.id
}
})
};
},
cache: true
},
//define min input length
minimumInputLength: 3,
});
And i want setup a data-source for the selected option value.
I find the solution, looks that resultTemplate dont format the "visual" selected option , need to use templateSelection option:
templateSelection: function(container) {
$(container.element).attr("data-source", container.source);
return container.text;
}
I solved this problem.
$('select').on('select2:select', function (e) {
var data = e.params.data;
$("select option[value=" + data.id + "]").data('source', data.source);
$("select").trigger('change');
});
You can actually use the exact syntax, that you already used. The "source-attribute" just needs to be accessed via data().data.source of the specific select2-option.
So keep your processResults function like you did:
processResults: function (data) {
return {
results: $.map(data, function (item) {
return {
text: item.name,
source: item.source,
id: item.id
}
})
};
},
and if you want to retrieve the source of the selected option, you can do it like this:
var selectedSelect2OptionSource = $("#idOfTheSelect2 :selected").data().data.source;
In fact you can set any variable you want in your processResults function and then select it via data().data.variableName!
Related
I have this code for select2 tags method using ajax:
json data:
[
{
"id": "5",
"text": "laravel3"
},
{
"id": "4",
"text": "laravel2"
}
]
Code:
$(document).ready(function(){
$('#tag_list').select2({
placeholder: "Choose tags...",
tags: true,
minimumInputLength: 3,
tokenSeparators: [",", " "],
createSearchChoice: function(term, data) {
if ($(data).filter(function() {
return this.text.localeCompare(term) === 0;
}).length === 0) {
return {
id: term,
text: term
};
}
},
ajax: {
url: '/tags/find',
dataType: 'json',
data: function (params) {
return {
q: $.trim(params.term)
};
},
processResults: function (data) {
return {
results: data
};
},
delay: 250,
cache: true
}
});
});
With my code I can search and select data from database or add new tag to my select2 area. Now when I select data from database, <option value=""> is data id but when I add new tag <option value=""> is name(text) like this:
Now I need to change option value (get database data) from data id to data name (text). How do change option data value from id to name?!
Update: I've added more background and references to the docs, and switched the JSFiddle to using $.map() as the docs do.
The Select2 data format is described in the docs:
Select2 expects a very specific data format [...] Select2 requires that each object contain an id and a text property. [...] Select2 generates the value attribute from the id property of the data objects ...
The docs also describe how to use something other than your id:
If you use a property other than id (like pk) to uniquely identify an option, you need to map your old property to id before passing it to Select2. If you cannot do this on your server or you are in a situation where the API cannot be changed, you can do this in JavaScript before passing it to Select2
In your case, this would mean transforming the data you get back from your AJAX call, so that the id element of each result is actually the text value.
You can do that with the processResults() AJAX option. To do that using $.map as the docs do:
processResults: function (data) {
return {
// Transform data, use text as id
results: $.map(data, function (obj) {
obj.id = obj.text;
return obj;
})
};
}
Here's a working JSFiddle. Note I've set it up to simulate your real AJAX request using JSFiddle's /echo/json async option.
And here's a screenshot of the generated source, showing the value of both added tags, and those retrieved via AJAX, are the name (text):
Try this:
ajax: {
url: '/tags/find',
dataType: 'json',
data: function (params) {
return {
q: $.trim(params.term)
};
},
//updated
processResults: function (data) {
var newData = [];
$.each(data, function (index, item) {
newData.push({
id: item.id, //id part present in data
text: item.text //string to be displayed
});
});
return { results: newData };
},
//
delay: 250,
cache: true
}
I'm using Select2 4.0.6-rc.0 from Jquery, the thing is that when I copy and paste a value to be searched and there is only one option, that option is disabled and I can select it nor click it.
In this image I'm expecting only one results cause SF190 belongs to only one user.
But if the search brings more than one result everything is ok, like in this image:
This is the piece of code I'm using to initialize the Select2:
$('.js-data-example-ajax').select2({
width: '100%',
minimumInputLength: 1,
tags: [],
ajax: {
url: '<URL of my action>',
type: "POST",
dataType: "json",
delay: 1000,
data: function (term) {
return {
query: term.term
};
},
processResults: function (data) {
var res = data.map(function (item) {
return { id: item.Id, text: item.Id + ' ' + item.Name };
});
return {
results: res
};
}
}
});
I really don't know whats going on and I can't find any related solutions.
Here's a working codepen based on your example (and another codepen):
$( ".select2" ).select2({
ajax: {
url: "<url>",
dataType: 'json',
delay: 1000,
//type: "POST",
tags: [],
data: function (params) {
return {
q: params.term // search term
};
},
processResults: function (data) {
var res = data.map(function (item) {
return { id: item.id, text: item.text };
});
return {
results: res
};
},
},
minimumInputLength: 1
});
The only difference is that I removed the request type - I'm pretty sure that you are getting the data here, not posting it :) And if you try to put it back, the filter stops working, albeit in a different way (it returns the full list no matter what you put in the filter), so it might be the source of your problem here.
There is one more thing to consider - are you sure that there is no other code affecting your selectbox? Like something that applies to the .js-data-example-ajax, or any <span> with a single child (that's what a Select2 dropdown part is) etc.
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 use the select2 plugin from jquery and get my data over an ajax load. When I set the response I want to add attributes to the li-elements of my dropdown.
I already tried it with calling a function in "templateResult" but there I can only give back the vakue which is IN the <li></li> tags
My javascript:
var autocomplete = function () {
$("body").find("#myDropDown").select2({
language: "es",
ajax: {
url: searchDataUrl,
type: "POST",
// dataType: 'json',
delay: 250,
data: function (params) {
return {
term: params.term, // search term
page: params.page
};
},
processResults: function (data, params) {
return {
results: data.userData,
pagination: {
more: (params.page * 30) < data.total_count
}
};
},
cache: true
},
createTag: function (params) {
var term = $.trim(params.term);
if (term === '') {
return null;
}
return {
id: term,
text: term,
newTag: true // add additional parameters
}
},
escapeMarkup: function (markup) { return markup; },
minimumInputLength: 3,
templateResult: formatReponse, //With this it doesnt work
});
};
And the function from my templateResult Call:
//When I do this, I have a "<li>"-Tag within a "<li>"-Tag
var formatReponse = function (data) {
return '<li data-id="'+data.id+'" class="select2-results__option" role="treeitem">'+data.text+'</li>';
};
Can anybody help me with this? THANKS!
use the .attr(att,val) function like this:
Give your <li> an id name like liID in <li id='liID'> the following example
then give the name of the attribute you want to change in the example given as attributeToChange then give the value you want to set in the atribute in the example: valueToSet. good luck
$('#liID').attr('attributeToChange', 'valueToSet');