the processResult in select2 do not working - javascript

I use select2 loading remote data I send an ajax request and get the response correctly but the processResult don't run and nothing will be show
the javascript code :
var formatProduct=
function(product) {
console.log("formatProduct");
if (product.loading) return product.text;
var markup = '<div class="product-to-compare" data=' + product.id + '>' + product.name + '</div>' ;
return markup;
}
var formatProductSelection =
function (product) {
console.log("formatProductSelection");
return product.name || product.text;
}
$(".js-data-example-ajax").select2({
placeholder: "Search for product",
minimumInputLength: 2,
ajax: {
url: '/product/ajax_product_list/',
dataType: 'json',
quietMillis: 300,
data: function (params) {
var id = $('#product-no-1').attr('data') ;
return {
key: params,
id: id
};
},
processResults: function (data) {
return {
results: data.items
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatProduct, // omitted for brevity, see the source of this page
templateSelection: formatProductSelection // omitted for brevity, see the source of this page
});
and the JSON that my controller return as a response :
{
"items": [
{"id": "55dd980c8242b630cfaf4788", "name": "sallll"},
{"id": "55d58d7a8242b62c6b88504e", "name" : "inja"},
{"id": "55d58d558242b62c6b88504d", "name": "salam"}
]
}

You should rename your JSON to return text instead of name.
Note that if you're using an older version of select2 (<4) you should use results instead of processResults.

processResults: function (data) {
//There is my solution.Just directly manipulate the data
$.each(data.items, function(i, d) {
data.items[i]['text'] = d.name;
});
return {
results: data.items
};
}

In my case, I was refreshing the page and looking for the http request sent to fetch search data. So make sure you do a search to processResult get called.

In your JSON data, you rename name to text. Because select2 data only accepts column names id and text.

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
}

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!

two ajax request url (success/fail)

Good day,
I was in some disarray . I have a ajax request from select2. Also I have two urls. How should I event organized If / else success/failure statements, if suddenly one will not work , then send an inquiry to another link?
I'm trying again and again and alwas there is error somewhere((
$(".js-data-example-ajax").select2({
language: "ru",
placeholder: "Serach.........",
disabled: false,
selected: true,
ajax: {
url: "url_1",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term + "%", // search term
};
},
processResults: function (data) {
if (data.features.length > 0) {
var resultArray = [];
$.each(data.features, function (index, value) {
value.attributes.id = value.attributes.OBJECT_ID;
resultArray.push(value.attributes);
});
return {
results: resultArray
};
} else {
return []
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
minimumInputLength: 5,
templateResult: formatRepo, // omitted for brevity, see the source of this page
templateSelection: formatRepoSelection // omitted for brevity, see the source of this page
});
It should be quite simple because you only have to call the first url and, on error, call the second.
$.ajax(function(data){
url: "url_1",
...,
success(function(data){
//do stuff on success
}),
error(function(e){
$.ajax(function(data{
//call the second url
})
})
})

Select2 JS Loading remote data with Ajax

I am using Select2 JS Version 4.0.0-rc.1 and having trouble loading suggestions with remote Ajax method.
Below are the markups and code
<select class="form-control input-sm" id="selFrame1" name="selFrame1">
<option> Select Frame </option>
</select>
the JavaScript Jquery
$('#selFrame1').select2({
ajax: {
url: siteUrl+"suggest/frames",
dataType: 'json',
delay: 250,
method:'POST',
data: function (params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function (data, page) {
// 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
return {
results: data.result
};
},
cache: true
}
});
The Json Result returned by server
{results: [{"Code":"123360000"},{"Code":"123360358"},{"Code":"123364000"},{"Code":"123400000"}], more: false }
I am totally not sure if I need to write specific functions to show suggestions, the comments on the Ajax section say that we should not alter the result Json data.
Now somebody please tell me what more I should to get the code working to show the suggestions.
I guess with the new version of select2 a lot of stuffs have changed.
Your response is being returned as a Select2 3.x response, which is fine. We've provided the processResults method because of this (previously results) so you can modify the response on the client side.
In your case, your response includes the results key but your processResponse function is referencing a result key which does not exist. If you change it to something like
processResults: function (data, page) {
// 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
return {
results: data.results,
pagination: {
more: data.more
}
};
},
Then things should start working. This also maps the existing more property on the response to the new pagination key that we migrated to in Select2 4.0.
Your Json response has to be like this :
{
"total_count":2,
"items": [
{"id":"01", "name":"item 1"},
{"id":"02", "name":"item 2"}
]
}
To work, you an id property.
Here is my config :
function formatRepo (repo) {
if (repo.loading) return repo.text;
var markup = "<div class='select2-result-repository clearfix'><div class='select2-result-repository__img'><img src='" + repo.img + "' width='80' height='80' /></div><div class='select2-result-repository__meta'><div class='select2-result-repository__title'>" + repo.full_name + "</div>";
markup += "<div class='select2-result-repository__statistics'><div class='select2-result-repository__type'><i class='fa fa-flash'></i> Type : " + repo.type + "</div><div class='select2-result-repository__usecase'><i class='fa fa-eye'></i> Use case : " + repo.usecase + "</div></div></div></div>";
return markup;
}
function formatRepoSelection (repo) {
return repo.full_name;
}
// Init select2
$(".select2").select2({
ajax: {
type : "GET",
url : "{{ path('tag_search_js') }}",
dataType: 'json',
delay : 250,
data : function (params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function (data, params) {
params.page = params.page || 1;
return {
results: data.items,
pagination: {
more: (params.page * 30) < data.total_count
}
};
},
cache: true
},
placeholder: "Select a tag",
escapeMarkup: function (markup) { return markup; },
minimumInputLength: 1,
templateResult: formatRepo,
templateSelection: formatRepoSelection
});
Hope this helps !

Loading remote data only once with Select2

As the title suggests I would like to load remote data once only.
I thought about loading a data with independent ajax call and set it "locally" at the control but wonder if there is more "built in" way to do so...
a solution can be found here:
https://github.com/ivaynberg/select2/issues/110
$("#selIUT").select2({
cacheDataSource: [],
placeholder: "Please enter the name",
query: function(query) {
self = this;
var key = query.term;
var cachedData = self.cacheDataSource[key];
if(cachedData) {
query.callback({results: cachedData.result});
return;
} else {
$.ajax({
url: '/ajax/suggest/',
data: { q : query.term },
dataType: 'json',
type: 'GET',
success: function(data) {
self.cacheDataSource[key] = data;
query.callback({results: data.result});
}
})
}
},
width: '250px',
formatResult: formatResult,
formatSelection: formatSelection,
dropdownCssClass: "bigdrop",
escapeMarkup: function (m) { return m; }
});
Edit:
I might have misinterpreted your question. if you wish to load all data once, then use that is Select2, there is no built in functionality to do that.
Your suggestion to do a single query, and then use that stored data in Select2 would be the way to go.
This is for Select2 v4.0.3:
I had this same question and got around it by triggering an AJAX call and using the data returned as the initialized data array.
// I used an onClick event to fire the AJAX, but this can be attached to any event.
// Ensure ajax call is done *ONCE* with the "one" method.
$('#mySelect').one('click', function(e) {
// Text to let user know data is being loaded for long requests.
$('#mySelect option:eq(0)').text('Data is being loaded...');
$.ajax({
type: 'POST',
url: '/RetrieveDropdownOptions',
data: {}, // Any data that is needed to pass to the controller
dataType: 'json',
success: function(returnedData) {
// Clear the notification text of the option.
$('#mySelect option:eq(0)').text('');
// Initialize the Select2 with the data returned from the AJAX.
$('#mySelect').select2({ data: returnedData });
// Open the Select2.
$('#mySelect').select2('open');
}
});
// Blur the select to register the text change of the option.
$(this).blur();
});
This worked well for what I had in mind. Hope this helps people searching with the same question.
To load data once:
Assumptions:
You have a REST API endpoint at /services that serves a JSON array of objects
The array contains objects which have at least a "name" and "id" attribute. Example:
[{"id": 0, "name": "Foo"}, {"id": 1, "name": "Bar"}]
You want to store that array as the global 'services_raw'
First, our function to load the data and create the global 'services_raw' (AKA 'window.services_raw'):
fetchFromAPI = function() {
console.log("fetchFromAPI called");
var jqxhr = $.ajax(
{
dataType:'json',
type: 'GET',
url: "/services",
success: function(data, textStatus, jqXHR) {
services_raw = data;
console.log("rosetta.fn.fetchServicesFromAPI SUCCESS");
rosetta.fn.refreshServicesSelect();
},
error: function(jqXHR, textStatus, errorThrown) {
console.log("Error inside rosetta.fn.fetchServicesFromAPI", errorThrown, textStatus, jqXHR);
setTimeout(rosetta.fn.fetchServicesFromAPI(), 3000); // retry in 3 seconds
}
}
)
.done(function () {
console.log("success");
console.log(jqxhr);
})
.fail(function () {
console.log("error");
})
.always(function () {
console.log("complete");
});
// Perform other work here ...
// Set another completion function for the request above
jqxhr.always(function () {
console.log("second complete");
});
};
Second, our Select2 instantiation code which transforms our data into a format that Select2 can work with:
refreshServicesSelect = function () {
// ref: http://jsfiddle.net/RVnfn/2/
// ref2: http://jsfiddle.net/RVnfn/101/ # mine
// ref3: http://jsfiddle.net/RVnfn/102/ # also mine
console.log('refreshServicesSelect called');
$("#add-service-select-service").select2({
// allowClear: true
data: function() {
var arr = []; // container for the results we're returning to Select2 for display
for (var idx in services_raw) {
var item = services_raw[idx];
arr.push({
id: item.id,
text: item.name,
_raw: item // for convenience
});
}
return {results: arr};
}
});
};
Here's what the Select2 element in HTML should look like before your call the above functions:
<input id="add-service-select-service" type="hidden" style="width:100%">
To use all of this, call (in JS):
window.fetchFromAPI();
window.refreshServicesSelect();
Lastly, here's a JSFiddle where you can play with a similar thing: http://jsfiddle.net/RVnfn/102/
Basically, in my example above, we're just using ajax to populate the equivalent of window.pills in the Fiddle.
Hope this helps :)
Please reply if you know how to do this via the Select2 .ajax function, as that would be a bit shorter.
In my condition, it is working perfectly with the given code
$('#itemid').select2({
cacheDataSource: [],
closeOnSelect: true,
minimumInputLength: 3,
placeholder: "Search Barcode / Name",
query: function(query) {
// console.log(query);
self = this;
var key = query.term;
var cachedData = self.cacheDataSource[key];
if(cachedData) {
query.callback({results: cachedData});
return;
} else {
$.ajax({
url: "./includes/getItemSelect2.php",
data: { value : query.term },
dataType: 'json',
type: 'POST',
success: function(data) {
self.cacheDataSource[key] = data;
query.callback({results: data});
}
});
}
},
});
And my data return from the ajax is in this form
<?php
$arr = [
["id" => 1, "text" => "Testing"],
["id" => 2, "text" => "test2"],
["id" => 3, "text" => "test3"],
["id" => 4, "text" => "test4"],
["id" => 5, "text" => "test5"]
];
echo json_encode($arr);
exit();
?>

Categories