xeditable & select2 dropdown w/ajax source displaying empty after submitting - javascript

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
};
}
}
}
});

Related

change option data value in select2 ajax tags

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
}

Why Select2 from Jquery shows me a disabled options when I paste in the search input?

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.

Set data of a Multiple Select2 element through javascript

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>

set data attributes with ajax and select2

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!

How to reset the data after init , Select2

I use Select2-4.0.0 I have been struggling with this problem for a whole day that to update the data.
I search every posts I can like Update select2 data without rebuilding the control, but none have them work.
What I need is really simple (a setter to data):
I have a diaglog, which had a select. Every time I open the diaglog, I will ajax for an data to keep it in a local array like:
when dialog open :
var select2List=syncToLoadTheData();//data for select2
$('#search-user-select').select2({ //here when secondly executed, the select2's data on UI does not refreshed
data:select2List,
matcher: function(params, data){
var key = params.term;
if ($.trim(key) === '') {
return data;
}
if( (matchKeyAndPinyin(key,data.text))){
return data;
}
return null;
}
}
But the problem is even though the list is changing, the select options does not change at all.Please note in my test case, every time i open the dialog, the data from server is changed:
What I had tried:
1.when init:
data: function() { return {results: select2List}; }// not work to show any data at all
2.when secondly open dialog:
$( "#search-user-select").select2('data',newdata,true);//not work to have the new data
3.when secondly open:
$("#search-user-select").select2("updateResults");//Error, does not have this method
And some other method like directly change the array's data(only one copy of the data), but none of them work.
I had the same problem before, my problem was i need to update the select2 after every ajax request with new data.
and this how i fixed my code.
EventId = $(this).attr('id');
$.ajax({
url: 'AjaxGetAllEventPerons',
type: 'POST',
dataType: 'json',
data: {id: EventId},
})
.done(function(data) {
$("#select2_job").select2({
minimumInputLength: 2,
multiple:true,
initSelection : function (element, callback) {
//var data = data;
callback(data);
},
ajax: {
url: "/AjaxGetAllPersonForEvent",
dataType: 'json',
quietMillis: 100,
data: function (term) {
return {
term: term
};
},
results: function (data) {
var myResults = [];
$.each(data, function (index, item) {
myResults.push({
'id': item.id,
'text': item.fullname
});
});
return {
results: myResults
};
}
}
});
I hope this example will help you to solve your problem

Categories