Select 2 displaying undefined using initSelection ajax call - javascript

I'm trying to preload an entry into Select2 using a remote ajax call and the initSelection function. My question seems to be similar to this question, however both answers don't work for me.
The call works and returns the correct result in json format, the issue appears to be with the callback not sending the data object in the right format.
j("#selectElement").select2({
placeholder: "Placeholder text",
multiple: false,
minimumInputLength: 1,
ajax: {
url: "/getfiles",
dataType: 'json',
data: function (term, page) {
return {
q: term //search term
};
},
results: function (data, page) {
return data;
}
},
initSelection: function(element, callback) {
return j.getJSON("/getfiles?id=" + (element.val()), null, function(data) {
if (j.isFunction(callback)) {
//alert(JSON.stringify(data, null, 4));
return callback(data);
}
});
}
});
When I alert the data object it returns this data:
{
"results": [
{
"id": "1",
"text": "Name of the file"
}
],
"more": "false"
}
The end result is the text "undefined" being loaded into the select2 input.
I would greatly appreciate any assistance.
Tim

The solution is to format the callback data like this
return callback(data.results[0]);
Credit goes to this question/answer: Select2 and initSelection callback

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
}

How to provide a datasource for Select2 with October CMS via the built in Ajax Framework

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'
},
// ...
});

Another way to load remote data in Select2

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>.

Select2 Plugin not eliminating options based on input

I am trying to work with the Select2 plugin in conjunction with the CodeIgniter framework. After a lot of effort, I managed to get it to work with AJAX data. However, now it has a weird problem. Even after typing in the entire name, the plugin does not eliminate the irrelevant options that do not match with the search term.
The below screenshot depicts this.
http://i.imgur.com/MfLcuf6.jpg?1
The Firebug console looks like this:
http://i.imgur.com/Qvko6mX.jpg
Below is my the Javascript code as well as the code for my controller
Javascript:
$("#mentor-typeahead").select2({
width: "100%",
placeholder: "Enter a mentor name",
maximumSelectionSize: 5,
minimumInputLength: 2,
multiple: true,
ajax: {
url: 'get_mentor_multi_list',
quietMillis: 500,
cache: true,
dataType: 'json',
results: function (data) {
return { results: data };
}
}
});
Controller
function get_mentor_multi_list($query = null)
{
$answer = array(array('id'=>1, 'text'=>'Inigo Montoya'),
array('id'=>2, 'text'=>'Zoey Deschanel'),
array('id'=>3, 'text'=>'Harry Potter'),
array('id'=>4, 'text'=>'Nicole Scherzinger'),
array('id'=>5, 'text'=>'Xerxes Mistry'),
array('id'=>6, 'text'=>'Tom Marvollo Riddle'),
array('id'=>7, 'text'=>'Light Yagami'),
array('id'=>8, 'text'=>'Vic Mackey'),
array('id'=>9, 'text'=>'Clark Kent'));
echo json_encode($answer);
}
I am utterly confused as to what could be causing the problem. I also tried the solution listed here link but to no avail. Any help would be appreciated.
Changed the AJAX call parameters on request but the output remains the same...
$("#mentor-typeahead").select2({
width: "100%",
placeholder: "Enter a mentor name",
maximumSelectionSize: 5,
minimumInputLength: 2,
multiple: true,
ajax: {
url: 'get_mentor_multi_list',
quietMillis: 200,
dataType: 'json',
data: function (term, page) {
return {
q: term,
page_limit: 10
};
},
results: function (data, page) {
return data;
}
}
You're missing a data function in the ajax part. See Loading Remote Data and Infinite Scroll with Remote Data in the documentation.
ajax: {
url: "http://api.rottentomatoes.com/api/public/v1.0/movies.json",
dataType: 'jsonp',
quietMillis: 100,
data: function (term, page) { // page is the one-based page number tracked by Select2
return {
q: term, //search term
page_limit: 10, // page size
page: page, // page number
apikey: "ju6z9mjyajq2djue3gbvv26t" // please do not use so this example keeps working
};
},
results: function (data, page) {
var more = (page * 10) < data.total; // whether or not there are more results available
// notice we return the value of more so Select2 knows if more results can be loaded
return {results: data.movies, more: more};
}
}
You're not using the ajax function correctly. It's doing exactly what it's supposed to do and that is to display all of the data returned from your get_mentor_multi_list() function.
In order to do this correctly, your ajax call needs to include a data attribute that includes parameters to be sent to your get_mentor_multi_list() function. get_mentor_multi_list() will then return only the results that your user is looking for.
If the data in get_mentor_multi_list() is static (i.e. not read from any database), you should consider adding it to the data attribute like in the Loading Array Data example here.
Finally, I was able to resolve the problem by myself. The problem lay in the fact that I was using CodeIgniter. Hence whatever variables that were supposed to be passed through the data attribute of the AJAX call weren't actually being passed to the controller.
I resolved this by changing the Javascript code to the following:
JavaScript
$('#mentor-typeahead').select2({
width: "100%",
placeholder: "Enter a mentor name",
maximumSelectionSize: 5,
minimumInputLength: 2,
multiple: true,
ajax: {
url: 'get_mentor_multi_list',
quietMillis: 200,
dataType: 'json',
data: function (term, page) {
return {
searchq: term // set the search term by the user as 'searchq' for convenient access
};
},
results: function (data, page) {
return {
results: data
};
}
}
});
And the controller code to look something like the following:
function get_mentor_multi_list()
{
// model code
$query = trim($_GET['searchq']); // get the search term typed by the user and trim whitespace
if(!empty($query))
{
// retrieve data from database
}
else
{
$answer = array('id' => 0, 'text' => 'No results found');
}
echo json_encode($answer);
}

angular-ui select2 initSelection not getting called

I have an angular-ui select2 component on my page. It works fine when the user types something in (it uses ajax to load in the data).
But the initSelection function never gets called. Here's the configuration object I pass into the select2
{
multiple: true,
minimumInputLength: 1,
tokenSeparators: [",", " "],
createSearchChoice: function (term) {
return term;
},
width: 'resolve',
ajax: {
url: '...',
method: 'GET',
quietMillis: 100,
data: function (term, page) {
...
},
results: function (data, page) {
...
}
},
initSelection: function (element, callback) {
console.log('initSelection');
return $.ajax({
url: "...",
type: "GET",
data: {
...
},
}).done(function(data) {
console.log(data);
return callback(data);
});
}
};
"initSelection" never gets logged to the console. Why isn't initSelection getting called?
initSelection is only called when there is initial input to be processed (see blue box just above here - the closest place to link to, I'm afraid). I suspect this may be your problem from the way the question is worded.
I'm able to do selected value as Edit time using InItSelection in Angular Js.
$scope.partInitSelection = function (element, callback) {
var resultArray = [];
resultArray.push({ id: "1", text: "hi" });
$scope.HospitalizationView.HospitalName = resultArray[0];
callback(resultArray[0]);
};

Categories