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);
}
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 Select2 js library but I can't not put the links into the select options.
Here is my json structure
[{id: 1, title: "Foo", slug: "foo"}]
And my select2 script
$(".search-box").select2({
placeholder: "Enter...",
ajax: {
url: window.location.href + '/search',
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term // search term
};
},
processResults: function (data) {
// 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: $.map(data, function (item) {
return {
text: item.title,
id: item.id
}
})
};
},
cache: true
},
minimumInputLength: 2,
maximumSelectionLength: 6
});
What I expect is when i type and click the title of SELECT OPTION i want the browser go to the post's address (link)
So any help plzzz
You cannot put window.location.href in the URL. Instead, use proper page URL path.
window.location.href is mainly use for page redirection.
I am using this jQuery plugin http://ivaynberg.github.io/select2/ with a data source linked to my employe database. The "Term" being used is last name however the jSON response is the full name.
When the result is Smith, John and you type smith it shows fine but when you try to include the first name to narrow it down even more, it stops the search as the comma is not part of the term.
$("[name=manager]").select2({
multiple: false,
minimumInputLength: 3,
placeHolder: 'Manager Last name',
allowClear: true,
ajax: {
url: "jsonUser.php",
dataType: 'json',
data: function (term) {
return {
term: term, // search term
};
},
results: function (data) { // parse the results into the format expected by Select2.
return {results: data};
}
},
});
The jSON response looks like this:
[{"id":"12345","text":"Smith, John"}
Anyone know of a way to make is so the full response is searchable and not just the term?
I have a select2 dropdown, which is configured for using with remote data. However, my remote datasource provides the search results in a format which seems to be not compatible with select2. The remote data is for example like this:
...
items: [ { value: 1, displayText: "First" }, { value: 2, displayText: "Second" } ]
...
but select2 seems to expect the "id" and "text" fields instead. I've checked all options, and tried to play with formatSelection, formatResult callbacks, but had no success until now, I always get javascript errors about "item.text" being undefined.
I cannot provide a jsFiddle because the web API is not public unfortunately.
Is there a way to configure select2 for using a custom "id" and "text" field? Or what else could be a good workaround for this scenario?
Ok, I figured it out almost immediately after I posted my question. Probably this is not the most efficient way to do this, so I'm still happy if someone has a better answer.
I managed to do a conversion in the results callback in the ajax options.
$("#mySelect").select2({
minimumInputLength: 3,
ajax: {
url: '/',
params: {
type: 'POST',
dataType: 'json',
},
quietMillis: 200,
data: function(term, page) { // page is the one-based page number tracked by Select2
return {
search: term,
pageSize: 10,
pageIndex: page-1,
};
},
results: function(data, page) {
var more = (page * 10) < data.Total; // whether or not there are more results available
return { results: $.map(data.Results, function(e, i) {
return { id: e.value, text: e.displayText, data: e };
}), more: more };
}
}
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>.