Related
So I'm using Datatables.JS to create a table of results returned from a MySQL database. When I return the results I'm trying to display them in DESC order. I have tried using ORDER BY DESC in my MySQLi query, this does return the results in the correct order, however when datatables is reading the results it's displaying them in some random order. So I've tried playing with the datatable settings to sort by my ID column but keep that column hidden. Whenever I attempt to add any code to handle the sorting, the sorting issue itself becomes resolved but all my pagination and buttons such as the buttons that allow the user to select which columns they would like to view just disappear. Below is the JS I'm using to select the features and setup I need for this datatable, can anyone show me how to add sorting by the ID column DESC into this without breaking it?
$(document).ready(function() {
$('#datatable').DataTable();
//Buttons examples
var table = $('#datatable-buttons').DataTable({
pageLength: 20,
lengthChange: false,
searching: false,
buttons: ['copy', 'excel', 'pdf', 'colvis']
});
table.buttons().container()
.appendTo('#datatable-buttons_wrapper .col-md-6:eq(0)');
} );
Adding ordering: and then selecting the column and defining the order seems to break all the other settings, I lose my pagination and default results length as well as all control buttons on the page.
$(document).ready(function() {
$('#datatable').DataTable();
//Buttons examples
var table = $('#datatable-buttons').DataTable({
pageLength: 20,
lengthChange: false,
searching: false,
buttons: ['copy', 'excel', 'pdf', 'colvis'],
order: [[ 1, desc ]]
});
table.buttons().container()
.appendTo('#datatable-buttons_wrapper .col-md-6:eq(0)');
} );
I have no idea why this solutions works and I still don't understand what caused the original problem but I did find a working piece of code posted under a loosely relevant problem on another forum. I combined that code with what I had already and it solved my problem. Hopefully this helps someone else out who may encounter the same issue.
$(document).ready(function() {
$('#datatable-buttons').DataTable( {
pageLength: 20,
lengthChange: false,
searching: false,
ordering: true,
order: [[ 3, 'DESC' ]],
dom: 'B1frtip',
buttons: [
'copy',
'excel',
'pdf',
'colvis'
]
});
table.buttons().container()
.appendTo('#datatable-buttons_wrapper .col-md-6:eq(0)');
});
Just wanted to mention this JS was for a datatable that's part of the Fonik Bootstrap Admin Template.
I have the following setup for jQgrid 5.1.0:
<div id="grid_container">
<table id="grid"></table>
<div id="gridpager"></div>
</div>
<script type="text/javascript">
$.fn.fmatter.btnFormatter = function (cellValue, options, rowData, addOrEdit) {
var btn =
'<a href="#">' +
'<img class="api_button" data-id="' + options.rowId + '" src="/images/icons/16x16/view.png" alt="Show API Response data" title="Show API Response data" />' +
'</a>' +
'<a href="#">' +
'<img class="error_button" data-id="' + options.rowId + '" src="/images/icons/16x16/view.png" alt="Show errors" title="Show errors" />' +
'</a>';
return btn;
};
$(function () {
$("#grid").jqGrid({
url: '/sf/api-logs',
datatype: "json",
colNames: {{ colNames|raw }},
colModel: {{ colFormats|raw }},
width: 980,
height: 300,
pager: "#gridpager",
toppager: true,
hoverrows: true,
shrinkToFit: true,
autowidth: true,
rownumbers: true,
viewrecords: true,
rowList: [10, 20, 50, 100],
data: [],
rownumWidth: 50,
sortable: true,
jsonReader: {
root: 'rows',
page: 'page',
total: 'total',
records: 'records',
cell: '',
repeatitems: false
},
loadComplete: function (data) {
if (data.records === 0) {
$("#load_grid").addClass("info_msg").html($("<span>", {
"class": "grid-empty",
"text": "No results were found."
})).delay(800).fadeIn(400);
}
}
}).on('click', '.api_button', function () {
var apiResponseContent = $('#apiResponseContent');
$.ajax({
type: "GET",
url: '/sf/api-logs/api-response',
data: {id: $(this).data('id')},
dataType: 'json',
success: function (data) {
if (typeof data[0].error !== 'undefined') {
apiResponseContent.text(data[0].error);
}
apiResponseContent.text(data[0].apiResponse);
$('#api_dialog').dialog('open');
}
});
return false;
});
$('#api_dialog').dialog({
autoOpen: false,
width: 600,
height: $(window).height() * 0.9,
modal: true,
buttons: {
Ok: function () {
$(this).dialog('close');
}
}
}).show();
});
</script>
But as the image below shown the pagination is not working and the small icon for refresh the grid is not being displayed either, what I am doing wrong here?
UPDATE
I have managed to show the refresh button by adding the following code:
$('#grid').jqGrid('navGrid', '#gridpager', {
edit: false,
add: false,
del: false,
search: false,
refresh: true,
refreshstate: "current"
})
But it only appears on the #gridpagger what about if I want it also on the top bar?
Here is an example of the data returned by the server: https://gist.github.com/reypm/b1d2a303ba471261e55d72bbef099b74
You reported about two problems: pagination not working and the Refresh button appears on the bottom pager only (not on the top-pager).
The problem with Refresh button seems be mostly simple. You use commercial Guriddo, which probably still have the same logic of working with pagers like jqGrid 4.7. Old jqGrid has two pager options: pager and toppager, which values have to be specified in different ways. Working with toppager is easy: one can add toppager: true option and jqGrid will generate the top-pager div itself and to replace the value of toppager from true to the id selector of new pager. It will be toppager: "#grid_toppager". On the other side, to create the pager on the bottom of the grid one have to create somewhere on the HTML page dummy div, like <div id="gridpager"></div> and to use pager parameter in the form pager: "gridpager". jqGrid will move the div on another place inside of the grid and to fill it with data. Other methods like navGrid, inlineNav, navButtonAdd have to use #gridpager or "#grid_toppager" as parameter to create the navigator bar and to add buttons to the bar. Thus you have to use the code like
$('#grid').jqGrid('navGrid', '#grid_toppager', {
edit: false,
add: false,
del: false,
search: false,
refreshstate: "current"
});
or
var $grid = $('#grid'),
topPagerSelector = $grid.jqGrid('getGridParam', 'toppager');
$grid.jqGrid('navGrid', topPagerSelector, {
edit: false,
add: false,
del: false,
search: false,
refreshstate: "current"
});
to create the navigator bar on the top-pager and to add the Refresh button to it. Alternatively you can use cloneToTop: true option of navGrid to add the same pagers to both pagers:
$('#grid').jqGrid('navGrid', '#gridpager', {
cloneToTop: true,
edit: false,
add: false,
del: false,
search: false,
refreshstate: "current"
});
You can't use the option if you want to have only one top pager. You will have to use '#grid_toppager' with navButtonAdd method.
I develop free jqGrid fork of jqGrid. I simplified the behavior already in the first version of free jqGrid published in the 2015: see the wiki article. One can use pager: true in the same way like toppager: true and one can skip pager parameter in navGrid, inlineNav, navButtonAdd. The usage of navGrid could be
$('#grid').jqGrid('navGrid', {
edit: false,
add: false,
del: false,
search: false,
refreshstate: "current"
});
to add the navigator buttons on all pagers of the grid (top, bottom or both).
It's only one small difference between free jqGrid and Guriddo jqGrid. There are hundreds of other changes. I recommend you to consider to migrate to free jqGrid even if you payed Guriddo jqGrid license. I'd recommend you to read the page with the base information about the usage of free jqGrid.
The paging of data don't work because the response from your server is wrong. It looks like
{
"page": 1,
"total": 0,
"records": 67,
"rows": [
{ "id": "590a363477336501ad44ab02", "dataObject": "Account", ...},
...
{ "id": "590c97197ad70f00575a310a", "dataObject": "AgreementHistory", ...}
]
}
You use datatype: "json" option without loadonce: true option, which corresponds server side paging. It means that jqGrid send to url requests with rows and page parameter. The first request, which send jqGrid will contains page=1&rows=20 (20 is the default value of rowNum parameter of jqGrid) and the server have to return 20 or less rows (return only one requested page of data). Additional total and records property informs jqGrid about the total number or pages and records. Based on the value of total parameter jqGrid will disable pager buttons and the user will be not able to make paging correctly.
One the other side, your server response contains wrong value of total property and all 67 rows instead of 20 requested rows. Other 47 rows of the serve response will be just ignored by jqGrid.
If you have scenario, where the total number of records is not large (like 67 in you case), then it's recommended to add loadonce: true option (and forceClientSorting: true additionally in case of usage free jqGrid) and to modify the server response to
[
{ "id": "590a363477336501ad44ab02", "dataObject": "Account", ...},
...
{ "id": "590c97197ad70f00575a310a", "dataObject": "AgreementHistory", ...}
]
with all rows of the grid. jqGrid will fill internal data parameter, it will change datatype to "local" automatically after the first loading the data. As the result paging, sorting and filtering/searching (try filterToolbar or search: true of navGrid) locally without any additional communication to the server. It essentially simplify the server code and improves the performance of jqGrid. Even relatively large number of rows can be processed very quickly if you use small enough page size (like rowNum: 20 or rowNum: 10). You can try the demo with 60000 rows, 15 columns and 25 rows per page. You can test the time of paging, sorting and filtering.
Im using ui-grid to load my data set. Here is my requirment;
step 01: I want to load dataset_01 (scope.gridOptions.data = res_01;).
step 02: I want to sort by First Name (Click by firstname column).
step 03: Click an external button and Reload ui-grid with an another data set (scope.gridOptions.data = res_02;).
Here is my result:
I dont want sort by First Name here for second dataset.
I want data without sorting. How can I do it ?
Expected result:
So I want to reload second data set without sorting (Means I want to remove first sorting before load second data set). how can I reset my ui-grid before load next data set (scope.gridOptions.data = res_01;).
How can I do it ?
Thank you. :)
You can set the sort property of your columnDefs to:
sort: {
direction: undefined,
}
and call for grid refresh using $sope.gridApi.core.refresh() after. This should re-render the whole grid and get rid of the sorting.
Visit this page: http://ui-grid.info/docs/#/api/ui.grid.core.api:PublicApi
After having instantiated your gridApi, you can just call:
$scope.gridApi.core.refresh();
Hope that helps! :)
Create your gridoption like this
example
$scope.gridOptions = {
useExternalPagination: true,
useExternalSorting: false,
enableFiltering: false,
enableSorting: true,
enableRowSelection: false,
enableSelectAll: false,
enableGridMenu: true,
enableFullRowSelection: false,
enableRowSelection: false,
enableRowHeaderSelection: false,
paginationPageSize: 10,
enablePaginationControls: false,
enableRowHashing: false,
paginationCurrentPage:1,
columnDefs: [
{ name: "FristName", displayName: "Frist Name", width: '6%', sort: { direction: undefined } },
]
};
after that you can remove the sorting where you want using below code
$scope.RemoveSorting = function ()
{
$scope.gridOptions.columnDefs.forEach(function (d) {
d.sort.direction = undefined;
})
}
I'm using jqGrid and have setup an action handler where I want the user to be able to delete a row. The callback specified in the URL is being called, but I can't figure out how to pass the row ID to the URL handler so I know which row to delete.
Anyone have a solution to this?
<script>
$( document ).ready(function() {
$("#list2").jqGrid({
url:'datahandler',
datatype: "json",
colNames:['Name','Description', 'Data (Abbreviated)', 'Actions'],
colModel:[
{name:'name',index:'name', width:300, resizeable:true},
{name:'description',index:'description', width:300, resizeable:true},
{name:'data',index:'data', width:600, resizeable:true},
{name : 'actions', sortable:false, index: 'actions', formatter:'actions',
formatoptions: {
keys: true,
editbutton: false,
delOptions: { url: 'deleterow' }
}}
],
rowNum:10,
rowList:[10,20,30],
pager: '#pager2',
sortname: 'name',
viewrecords: true,
sortorder: "desc",
caption:"PVSyst Data",
});
$("#list2").jqGrid('navGrid','#pager2',{edit:false,add:false,del:false});
});
</script>
It's not clear which format exactly you use to fill the grid and which rowid you use. Typical error exist if the data wrong filled and the values 1, 2, 3 will be used instead of rowids which you want to see on the server side. In any way the above code will use HTTP POST request to the URL "deleterow" specified in delOptions. The data have the format described in the documentation of delGridRow (see here). For example if the id of deleted row is "123" then the data posted to the URL "deleterow" will be
oper=del&id=123
You need just implement reading of the id parameter on the server side. If you want to rename the name of parameter from id to any other text like myId then you can use jqGrid option prmNames: { id: "myId" }. After that the posted data will look like
oper=del&myId=123
The custom_value of place_id is set to whichever row I click first. Subsequent clicked rows will all use that same value, regardless of their actual value. Why?
example:
place_id foo_name bar_value
10 blah abc
11 blah2 fgr
click the row with the place_id of 10 and click "edit" and the form that appears will have 10 for the place_id value. Make a change and save it then click the next row down. The form will still have the place_id of 10 though all other values will be correct.
My code:
The column place_id looks like this:
{name:'place_id', index:'place_id', editable: true, edittype:'custom',
editoptions: { custom_element:myelem,custom_value:myval }}
The myval function is:
function myval(elem){
return elem.val();
}
What I need is for the myval to be set to the correct place_id for the row being edited. I looked at the elem object in Firebug and I see that it always has the value of whichever row was first clicked but I don't understand why nor do I see where I can grab the correct value from. Any suggestions are appreciated (I tried asking on the jqgrid forums but nothing came of it so I'm turning to stackoverflow).
*Edit: If I use edittype:'text' rather than edittype:'custom' I get the correct values displayed and passed but then the column is editable and it should only be visible but not editable.
Full code:
jQuery(document).ready(function(){
jQuery("#list").jqGrid({
url:'/foo/bar/results',
datatype: 'json',
mtype: 'POST',
colNames:['Place ID', 'Site ID', 'Site Name', 'API ID', 'M Type'],
colModel :[
{name:'place_id', index:'place_id', key: true, sorttype:'integer',
width:70, editable: true, edittype:'custom',
editoptions: {custom_element:myelem,custom_value:myval }},
{name:'site_id', index:'site_id', sorttype:'integer', width:70,
editable: true, edittype: 'select', editrule: {required: true},
editoptions:{value:getSites(), size:30}},
{name:'site_name', index:'site_name', width:150, editable: false,
editrule: {required: true}, editoptions: {size:30}},
{name:'api_id', index:'api_id', sorttype:'integer', width:75,
editable: true, edittype: 'text', editrules: {required: true},
editoptions:{size:30}},
{name:'m_type', index:'m_type', width:150, editable: true,
edittype: 'select', editrules: {required: true},
editoptions:{value:{'one':'one','two':'two','three':'three',
'four':'four'},size:30}}
],
editurl:'/foo/bar/editinfo',
height: 'auto',
width: 'auto',
pager: '#pager',
viewrecords: true,
loadonce: true,
rowNum:20,
rowList:[20,40,60,80,100],
caption: 'Meter Listing'
});
// Edit functionality
$("#editfields").click(function(){
var gr = jQuery("#list").jqGrid('getGridParam','selrow');
if( gr != null ) {
jQuery('#list').setGridParam({datatype:'json'});
jQuery("#list").jqGrid('editGridRow',gr,
{editCaption: 'Edit Place Details',height:550,
closeAfterEdit:true,width:600,reloadAfterSubmit:true});
} else {
alert("Please select a row");
}
});
});
function myelem(value,options){
return $('<input type="text" value="'+value+'" disabled="disabled"/>');
}
function myval(elem){
return elem.val();
}
edit2:
getSites:
function getSites(){
<?php
$sites = "0:Select";
foreach ($this->sites as $k => $v){
$sites = $sites . ";" . $v['site_id'] . ":" . $v['site_name'];
}
?>
return "<?= $sites ?>";
}
Could you try to include key: true in the definition of the place_id column. You can remove id from the data which you send from the server.
If it will not help, then you should post a full code example which reproduce your problem and I will try to find a workaround.
UPDATED: Sometime there are a simple solution for complex problems. One additional parameter of editGridRow function solve your problem:
recreateForm: true
Without using of the parameter the function myelem will be called only one time at the first edit of the selected row. Then the form will be cached and not recreated. So you will be edit always the same row. After including of the parameter recreateForm: true the form will be created every time.
By the way I set some general settings which I use in all jqGrids per extending jQuery.jgrid.defaults, jQuery.jgrid.edit, jQuery.jgrid.view, jQuery.jgrid.del and jQuery.jgrid.nav. For example I use always
jQuery.extend(jQuery.jgrid.edit, {
closeAfterAdd: true,
closeAfterEdit: true,
recreateForm: true,
//...
});
Then I don't need set this parameters later. During writing of the answer Add multiple input elements in a custom edit type field about custom editing I has also the settings, so I didn't see any problems.