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 !
Related
October CMS provides an extensive AJAX framework, that I'm looking to use to populate a Select2 box with.
According to Select2, using a remote dataset happens as follows:
$(".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) {
params.page = params.page || 1;
return {
results: data.items,
pagination: {
more: (params.page * 30) < data.total_count
}
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; },
minimumInputLength: 1,
templateResult: formatRepo,
templateSelection: formatRepoSelection
});
But from the October CMS docs, I cannot figure out how to pass the data to the server manually.
Questions are: which URL to use, and which parameters do I need to pass along so that October knows which function I want to access. Also, how can I capture the result without a partial being loaded?
This might be a trivial question; I might be looking in the wrong direction. Maybe the AJAX framework should not be used at all. Any insights on the correct way to proceed?
** EDIT FOLLOWING CORRECT ANSWER BY SAMUEL **
To make Select2 work with a remote dataset in combination with October CMS,
please take into account the following pitfalls. Below is my working code:
// SELECT 2
$('select').select2({
/*placeholder: "Your placeholder", // Remove this, this causes issues*/
ajax: {
// Use transport function instead of URL as suggested by Samuel
transport: function(params, success, failure) {
var $request = $.request('onSelect', {
data: params.data
});
$request.done(success);
$request.fail(failure);
return $request
},
dataType: 'json',
delay: 250,
data: function (params) {
console.log(params);
return {
q: params.term, // search term
page: params.page
};
},
processResults: function (data,params) {
console.log(data);
return {
// The JSON needs to be parsed before Select2 knows what to do with it.
results: JSON.parse(data.result)
};
},
cache: true
},
minimumInputLength: 1
});
Below is the example output I used in combination with this Select2 example:
[
{
"id":1,
"text":"Henry Kissinger"
},
{
"id":2,
"text":"Ricardo Montalban"
}
]
Above JSON was generated by my VisitorForm.php file:
<?php namespace XXX\VisitorRegistration\Components;
use Cms\Classes\ComponentBase;
use XXX\VisitorRegistration\Models\Visitor;
use October\Rain\Auth\Models\User;
class VisitorForm extends ComponentBase {
public function componentDetails()
{
return [
'name' => 'Visitor Form',
'description' => 'Description of the component'
];
}
// The function that returns the JSON, needs to be made dynamic
public function onSelect() {
return json_encode(array(array('id'=>1,'text'=>'Henry Kissinger'), array('id'=>2,'text'=>'Ricardo Montalban')));
}
}
VoilĂ , hope this can be useful.
Pass the transport option instead of url. Here is an example:
$(".js-data-example-ajax").select2({
ajax: {
transport: function(params, success, failure) {
/*
* This is where the AJAX framework is used
*/
var $request = $.request('onGetSomething', {
data: params.data
})
$request.done(success)
$request.fail(failure)
return $request
},
dataType: 'json'
},
// ...
});
I'm using Laravel5 with Jquery plugin Select2 in this cause I used Ajax to retrieve data from DB and display when using type any word.
Here is my Ajax.
$(".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
},
escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatRepo, // omitted for brevity, see the source of this page
templateSelection: formatRepoSelection // omitted for brevity, see the source of this page
});
Here is my HTML
<select class="js-data-example-ajax">
<option value="3620194" selected="selected">select2/select2</option>
</select>
But it is not work for me.
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.
I see this has been asked couple of times here, but none of them work for me. So i'm positing it again to see if someone faced something like this. I have a select2 inside a Model, and was able to populate it by making an ajax call to the Api. It works like a charm until here, problem is i'm not able to select any value into the 'Code'. Below is my code for the ajax and html
/HTML/
<div class="col-lg-8 col-sm-7">
<input id="procedureSelect" name="SelectProcedure" class="form-control">
</div>
/*Ajax Call */
$('#procedureSelect').select2({
placeholder: 'Select Procedure',
allowClear: true,
quietMillis: 1000,
ajax: {
url: '#Url.Action("GetProcedures", "Procedure")',
dataType: 'json',
data: function (term, page) {
return {
searchTerm: term,
page: page
};
},
results: function (data, page) {
var more = (page * 25) < data.total;
return { results: data.procedureData, more: more };
}
},
formatResult: function (data) {
return '<div>' + data.procedure_code + " - " + data.short_description + '</div>';
},
formatSelection: function (data) {
var result = data.procedureData;
return result.procedure_code;
}
});
I finally figured out the answer, by doing some more research. The Thing is select2 expects a unique Id for the data returned. So o added below one line of code to my javascript to assign the Id
id: function (data) { return data.procedure_code; },
Now it works fine.
I'm trying to get the remote using json from one php page,the JSON data:
[{"id":"0","name":"ABC"},{"id":"1","name":"DEF I"},{"id":"2","name":"GHI"}]
and the script is like this:
$(document).ready(function() {
$('#test').select2({
minimumInputLength: 1,
placeholder: 'Search',
ajax: {
dataType: "json",
url: "subject/data_json.php",
data: function (term, page) {// page is the one-based page number tracked by Select2
return {
college: "ABC", //search term
term: term
};
},
type: 'GET',
results: function (data) {
return {results: data};
}
},
formatResult: function(data) {
return "<div class='select2-user-result'>" + data.name + "</div>";
},
formatSelection: function(data) {
return data.name;
},
initSelection : function (element, callback) {
var elementText = $(element).attr('data-init-text');
callback({"name":elementText});
}
});
});
It works fine but it always reads the database whenever I typed one new character to search
. So i decided to use the another way (retrieve all data at first time and use select2 to search it):
$(document).ready(function() {
$("#test").select2({
createSearchChoice:function(term, data) {
if ($(data).filter(function() {
return this.text.localeCompare(term)===0; }).length===0) {
return {id:term, text:term};}
},
multiple: false,
data: [{"id":"0","text":"ABC"},{"id":"1","text":"DEF I"},{"id":"2","text":"GHI"}]
});
});
But the problem is how can I pass a request to data_json.php and retrieve data from it?
Say
data: $.ajax({
url: "subject/data_json.php",
data: function (term, page) {// page is the one-based page number tracked by Select2
return {
college: "ABC", //search term
};
}
dataType: "json",
success: function(data){
return data
}
}
But its not working, can anyone help?
Thanks
Why did you move away from your original code?
minimumInputLength: 1
Increase this and the search won't be called on the first character typed. Setting it to 3 for example will ensure the ajax call isn't made (and the database therefore not queried) until after the 3rd character is entered.
if I understood your question correctly you have data_json.php generating the options for select2 and you would like to load all of them once instead of having select2 run an ajax query each time the user inputs one or more characters in the search.
This is how I solved it in a similar case.
HTML:
<span id="mySelect"></span>
Javascript:
$(document).ready(function () {
$.ajax('/path/to/data_json.php', {
error: function (xhr, status, error) {
console.log(error);
},
success: function (response, status, xhr) {
$("#mySelect").select2({
data: response
});
}
});
});
I've found that the above does not work if you create a <select> element instead of a <span>.