Since I have switched to version 4 of the select2 plugin, my ajax calls do not work anymore.
I get a response in the form of an array which prints ok in the console but the results don't show in the select2 control.
http response :
{"results":{"id":"ok","term":"ok","description":"ok"}}
My code :
$(function(){
$('#appbundle_marketplace_product_ingredient_barcode').select2({
minimumInputLength: 3,
ajax:
{
delay: 250,
url: "{{ path('search_barcode') }}",
dataType: 'json',
debug: true,
data: function (params) {
// console.log(params.term);
return {barcode: params.term};},
processResults: function (data) {
console.log(data);
return data;
}
}
});
});
the data printed in the console is the following object :
Object {results: Object}
results: Object
description: "ok"
id: "ok"
term: "ok"
__proto__: Object
__proto__: Object
How can I have the select2 display a result in the dropdown, then click the result to have it selected ?
Thanks a lot,
Great question, same issue I ran into.
I had a similar issue, working in Wordpress. I had to update my php to return this:
// This prepared SQL query returns objects, so I thought I was fine
$partList = $wpdb->get_results( $sql );
// echo json_encode( $partList ); <- worked, but not quite right...
// Select2 wanted an array of items, so I added this
$jsonItems = array("items"=>$partList);
echo json_encode( $jsonItems );
In my JS I have this...
function formatPartSelection(ajaxData){
return ajaxData.commonName || ajaxData.text;
}
function formatAjaxResponse (ajaxData){
if(ajaxData.loading) return ajaxData.text;
var markup = '<div class="clearfix select2-result-selectable" style="border-bottom:solid; border-bottom-color: #D3D3D3">' +
'<div class="col-sm-10">' +
'<div class="clearfix">' +
'<div class="col-sm-10"><span style="font-weight: bold;">' + ajaxData.fieldOne + ' | ' + ajaxData.text + '</span></div>' +
'</div>';
if (ajaxData.description) {
markup += '<div class="col-sm-10">' +
'<div class="clearfix">' +
'<div><i>' + ajaxData.description + '</i></div>';
}
markup += '</div><br/></div>';
return markup;
}
$.fn.select2.amd.require(
["select2/core", "select2/utils", "select2/compat/matcher"],
function (Select2, Utils, oldMatcher) {
});
$('.myClass').select2({
placeholder: "Select part(s)...",
minimumInputLength: 3,
multiple: true,
ajax: {
url: url_to_your_php,
delay: 250,
type: "POST",
dataType: 'json',
data: function (params) {
var queryParameters = {
action: 'my_enqued_wp_ajax',
searchStringValue: params.term
}
return queryParameters;
},
processResults: function (data) {
console.log(data);
return {
results: data.items
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; },
templateResult: formatAjaxResponse,
templateSelection: formatPartSelection
});
The above code allowed me to get the list of items to select from working, but I couldn't actually click any of them. Many hours later, I found this answer which helped me to actually be able to select one of the values in my Select2 dropdown list:
https://stackoverflow.com/a/29082217/4266699
*Note, I had the luxury of creating a column in my DB called ID, so I was able to fix this on the backend.
Hope this helps!
Related
I can easily retrieve and format AJAX data to work with Select2, like this
function formatItem (item) {
if (!item.id) {
return item.text;
}
var _item = '<span class="' + item.deleted +'"><i class="fa fa-user"></i> ' + item.doctor + ', <small>' + item.sex + ' (' + item.user + ')</small></span>';
return $(_item);
}
var tabSelect = $('#t');
tabSelect.select2({
ajax: {
url: '../ajax/results.php',
data: function (params) {
return {
search: params.term,
page: params.page || 1
};
}
},
templateResult: formatItem,
templateSelection: formatItem
});
So far so good: <select> items are rendered correctly as HTML, with the nice Font-Awesome icon and the <small> tag.
User now selects an item and submits the (search) form. Of course I'd like to mark the current item as selected, and here comes the trouble.
Select2 docs have a way to predefine an AJAX retrieved item, but this works for simple text and not for rendered items with all the HTML bells and whistles
So, when adapting the provided example:
$.ajax({
type: 'GET',
url: '../ajax/results-selected.php', // url to retrieve a single item
data: {
iData: [here goes the ID for retrieving single item]
}
}).then(function (data) {
// create the option and append to Select2
var item = data.results[0];
console.log(item);
var option = new Option(item, item.id, true, true);
tabSelect.append(option).trigger('change');
// manually trigger the `select2:select` event
tabSelect.trigger({
type: 'select2:select',
params: {
data: data
}
});
});
I get the HTML rendered item, but with a series of undefined (please notice that console.log(item) returns the expected result: in other words, I have the fields but have no idea how to render them)
I tried lot of things, but none of them work, i.e.:
var option = new Option(formatItem(item), item.id, true, true);
I read around but could not find a valid solution working: please, any help?
I managed it to work by returning the whole HTML snippet in the JSON response (as text item)
// the JSON response
{
"results": [
{
"id": "1234",
"text": "<span class=\"\"><i class=\"fa fa-user\"></i> Doe John, <small>Mr. (Site Owner)</small></span>"
}
]
}
// the updated snippet
$.ajax({
type: 'GET',
url: '../ajax/results-selected.php', // url to retrieve a single item
data: {
iData: [here goes the ID for retrieving single item]
}
}).then(function (data) {
// create the option and append to Select2
var item = data.results[0];
console.log(item);
var option = new Option(item.text, item.id, true, true);
tabSelect.append(option).trigger('change');
// manually trigger the `select2:select` event
tabSelect.trigger({
type: 'select2:select',
params: {
data: data
}
});
});
I am using select2 dropdown and I am trying to build it as such that it dynamically displays the leads based on the JSON response.
As u can see in the image below, the text inserted correctly returns a JSON array, however, select2 is not capable of assigning the results into options. Therefore, I am literally quite stuck on what to do from here.
https://i.imgur.com/9OnvJzK.pnghere
I already tried setting a variable equal to the selectbox and appending the data in there, but my editor indicates that the code will be unreachable.
Create.tpl - contains front-end code
{literal}
<script>
$(document).ready(function() {
$('.select2lead').select2({
minimumInputLength: 3,
ajax: {
type: 'GET',
url: '/modules/support/ajax.php',
dataType: 'json',
delay: 250,
}
});
$('#select2lead').select2({
tags: true,
minimumInputLength: 3,
ajax: {
type: 'GET',
url: '/modules/support/ajax.php',
dataType: 'json',
delay: 250,
data: function (params) {
var query = {
search: params.term
};
// Query parameters will be ?search=[term]&type=public
return query;
},
processResults: function (data) {
var select2lead = $('#select2lead');
// Tranforms the top-level key of the response object from 'items' to 'results'
return {
results: data.items
}
// var option = new Option(data.name, data.id, true, true);
// select2lead.append(option).trigger('change');
}
}
});
$('#summernote').summernote({
height: 150,
minHeight: null,
maxHeight: null,
focus: true
});
})
</script>
{/literal}
ajax.php - handles the search term and returns JSON
<?php
require_once('../../config.php');
$login = new Login();
if (!$login->checkLogin()) {
echo lang($_SESSION['language'], "INSUFFICIENT_RIGHTS");
exit();
}
$db = new Database();
$query = "
SELECT
LeadID AS lead_id,
REPLACE(CONCAT_WS(' ', LeadInitials, LeadInsertion, LeadLastName), ' ', ' ') AS name,
REPLACE(CONCAT_WS(' ', LeadStreet, LeadStreetNumber, LeadNumberAdjective), ' ', ' ') AS address,
LeadZiPCode AS zipcode,
LeadCity AS city
FROM
`LeadTBL`
WHERE
LeadID > 0
AND
LeadLastName LIKE :leadName
ORDER BY
LeadLastName
ASC
";
$binds = array(':leadName' => $_GET['term'].'_%'.'_%');
$result = $db->select($query, $binds);
$json = [];
foreach ($result as $row){
$json[] = ['id'=>$row['lead_id'], 'name'=>$row['name']];
}
echo json_encode($json);
Issue resolved. Turns out I had to disable "more"; See https://groups.google.com/forum/#!msg/select2/4mDifie32t0/jdJl8KIFN0EJ
Regarding the final code that actually pastes the results into the dropdown properly, see:
$('.select2lead').select2({
minimumInputLength: 3,
ajax: {
type: 'GET',
url: '/modules/support/ajax.php',
dataType: 'json',
delay: 250,
data: function (params) {
return {
term: params.term
};
},
processResults: function (data) {
return {
results: data,
more: false
};
}
}
});
I want to use Select2 plugin to load remote data and customize select box. I followed documentation and it worked like a charm. But when user cannot find its match then message is displayed : "No results found."
Instead of the message my requirement is to have default option to be shown when user cannot find a match,similar to this http://prntscr.com/dodf8k
function formatRepo (repo) {
if (repo.loading) return repo.text;
var markup = '<div class="clearfix">' +
'<div clas="col-sm-10">' +
'<div class="clearfix">' +
'<div class="col-sm-6"><b>' + repo.full_name + '</b></div>' +
'</div>';
if (repo.description) {
markup += '<div>' + repo.description + '</div>';
}
markup += '</div></div>';
return markup;
}
function formatRepoSelection (repo) {
return repo.full_name || repo.text;
}
$(document).ready(function(){
$(".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, 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.items
};
},
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
});
});
I've made a fiddle with select2 plugin to load remote data. Please somebody tell me how do i accomplish this?
You should treat the case you have mentiond in your 'processResults' function like this (fiddle):
function formatRepo (repo) {
if (repo.loading) return repo.text;
var markup = '<div class="clearfix">' +
'<div clas="col-sm-10">' +
'<div class="clearfix">' +
'<div class="col-sm-6"><b>' + repo.full_name + '</b></div>' +
'</div>';
if (repo.description) {
markup += '<div>' + repo.description + '</div>';
}
markup += '</div></div>';
return markup;
}
function formatRepoSelection (repo) {
return repo.full_name || repo.text;
}
$(document).ready(function(){
$(".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, 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
if(data.items.length > 0) {
console.log(data.items);
return {
results: data.items
};
}
else return {results: [{ 'loading' : false, 'description' : 'others', 'name' : 'others', 'text' : 'others', 'full_name' : 'Some Name' }]}
},
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
});
});
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.js"></script>
<select class="js-data-example-ajax" style="width:100%">
<option value="3620194" selected="selected">Select a value......</option>
<option>others</option>
</select>
Here is my script for select2 multiple select box. I am using ajax for fetching the data. I need to add the current selections with existing values.
Ex : If 1000,1001 is already in the list. And if the user types 1002 it should merge with the old result and display as 1000, 1001, 1002.
Here is how i place the values in select2
In php i construct the options
foreach ($zips as $zipcodes) {
$pinLists .= $zipcodes->zipcode_id . ',';
$htmlElements .= '<li class="select2-selection__choice" title=""><span class="select2-selection__choice__remove" role="presentation">×</span>' . $zipcode->zipcode_id . '</li>';
}
Then in html i append to it
var htmlElement = '<?php echo $htmlElement ?>';
$(".firstSelect").append(htmlElement);
I tried like
$(".firstSelect").on('change', function(e) {
$(".firstSelect").append(htmlElement);
});
But i can't able to place the old values on change action.
Here is my entire script of select2 ajax
$("#firstList").select2({
ajax: {
url: "../getZipList",
type: "POST",
contentType: "application/json; charset=utf-8",
delay: 250,
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.items
};
//console.log(data.it)
},
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
});
How can i do this. Help pls
this is related to my previous question about jqgrid. im doing now a search button that would search my inputed text from the server and display those data (if there is) in the jqgrid. Now, what i did is i create a global variable that stores the filters. Here's my javascript code for my searching and displaying:
filter = ''; //this is my global variable for storing filters
$('#btnsearchCode').click(function(){
var row_data = '';
var par = {
"SessionID": $.cookie("ID"),
"dataType": "data",
"filters":[{
"name":"code",
"comparison":"starts_with",
"value":$('#searchCode').val(),
}],
"recordLimit":50,
"recordOffset":0,
"rowDataAsObjects":false,
"queryRowCount":true,
"sort_descending_fields":"main_account_group_desc"
}
filter="[{'name':'main_account_group_code','comparison':'starts_with','value':$('#searchCode').val()}]";
$('#list1').setGridParam({
url:'json.php?path=' + encodeURI('data/view') + '&json=' + encodeURI(JSON.stringify(par)),
datatype: Settings.ajaxDataType,
});
$('#list1').trigger('reloadGrid');
$.ajax({
type: 'GET',
url: 'json.php?' + $.param({path:'data/view',json:JSON.stringify(par)}),
dataType: Settings.ajaxDataType,
success: function(data) {
if ('error' in data){
showMessage('ERROR: ' + data["error"]["msg"]);
}
else{
if ( (JSON.stringify(data.result.main.row)) <= 0){
alert('code not found');
}
else{
var root=[];
$.each(data['result']['main']['rowdata'], function(rowIndex, rowDataValue) {
var row = {};
$.each(rowDataValue, function(columnIndex, rowArrayValue) {
var fldName = data['result']['main']['metadata']['fields'][columnIndex].name;
row[fldName] = rowArrayValue;
});
root[rowIndex] = row;
row_data += JSON.stringify(root[rowIndex]) + '\r\n';
});
}
alert(row_data); //this alerts all the data that starts with the inputed text...
}
}
});
}
i observed that the code always enter this (i am planning this code to use with my other tables) so i put the filter here:
$.extend(jQuery.jgrid.defaults, {
datatype: 'json',
serializeGridData: function(postData) {
var jsonParams = {
'SessionID': $.cookie("ID"),
'dataType': 'data',
'filters': filter,
'recordLimit': postData.rows,
'recordOffset': postData.rows * (postData.page - 1),
'rowDataAsObjects': false,
'queryRowCount': true,
'sort_fields': postData.sidx
};
return 'json=' + JSON.stringify(jsonParams);
},
loadError: function(xhr, msg, e) {
showMessage('HTTP error: ' + JSON.stringify(msg) + '.');
},
});
now, my question is, why is it that that it displayed an error message "Server Error: Parameter 'dataType' is not specified"? I already declared dataType in my code like above but it seems that its not reading it. Is there anybody here who can help me in this on how to show the searched data on the grid?(a function is a good help)
I modified your code based on the information from both of your questions. As the result the code will be about the following:
var myGrid = $("#list1");
myGrid.jqGrid({
datatype: 'local',
url: 'json.php',
postData: {
path: 'data/view'
},
jsonReader: {
root: function(obj) {
var root = [], fields;
if (obj.hasOwnProperty('error')) {
alert(obj.error['class'] + ' error: ' + obj.error.msg);
} else {
fields = obj.result.main.metadata.fields;
$.each(obj.result.main.rowdata, function(rowIndex, rowDataValue) {
var row = {};
$.each(rowDataValue, function(columnIndex, rowArrayValue) {
row[fields[columnIndex].name] = rowArrayValue;
});
root.push(row);
});
}
return root;
},
page: "result.main.page",
total: "result.main.pageCount",
records: "result.main.rows",
repeatitems: false,
id: "0"
},
serializeGridData: function(postData) {
var filter = JSON.stringify([
{
name:'main_account_group_code',
comparison:'starts_with',
value:$('#searchCode').val()
}
]);
var jsonParams = {
SessionID: $.cookie("ID"),
dataType: 'data',
filters: filter,
recordLimit: postData.rows,
recordOffset: postData.rows * (postData.page - 1),
rowDataAsObjects: false,
queryRowCount: true,
sort_descending_fields:'main_account_group_desc',
sort_fields: postData.sidx
};
return $.extend({},postData,{json:JSON.stringify(jsonParams)});
},
loadError: function(xhr, msg, e) {
alert('HTTP error: ' + JSON.stringify(msg) + '.');
},
colNames:['Code', 'Description','Type'],
colModel:[
{name:'code'},
{name:'desc'},
{name:'type'}
],
rowNum:10,
viewrecords: true,
rowList:[10,50,100],
pager: '#tblDataPager1',
sortname: 'desc',
sortorder: 'desc',
loadonce:false,
height: 250,
caption: "Main Account"
});
$("#btnsearchCode").click(function() {
myGrid.setGridParam({datatype:'json',page:1}).trigger("reloadGrid");
});
You can see the code live here.
The code uses datatype:'local' at the beginning (at the 4th line), so you will have no requests to the server if the "Search" button is clicked. The serializeGridData the data from the postData parameter of serializeGridData will be combined with the postData parameter of jqGrid (the parameter "&path="+encodeURIComponent('data/view') will be appended). Additionally all standard jqGrid parameters will continue to be sent, and the new json parameter with your custom information will additionally be sent.
By the way, if you want rename some standard parameters used in the URL like the usage of recordLimit instead of rows you can use prmNames parameter in the form.
prmNames: { rows: "recordLimit" }