I am using below code for creating custom formatter button :
colModel.push({ name : 'Id',index : 'Id', width: 100, sortable: false,
resizable: false, hidedlg: true, search: false, align: "center",
fixed: true, viewable: false,
formatter: function (cellvalue, options, rowObject) {
if (rowObject[8] === "Active") {
return "<button class=\"resend\">Resend</button>";
}
return "-";
}
});
JQGrid Code :
jQuery("#" + gridName).jqGrid({
url : gridUrl,
datatype : "json",
width : 1000,
height : 200,
colNames : colNames,
colModel : colModel,
rowNum : 20,
rowList : [ 10, 15, 20 ],
viewrecords : true,
pager : "#" + pager,
multiselect : false,
loadonce : true,
repeatitems: true,
imgpath : "themes/basic/images",
caption : "",
beforeSelectRow: function (rowid, e) {
return true;
},
}).navGrid("#" + pager, {
edit : false,
add : false,
del : false,
search : false,
refresh : false
}, {}, // Default for edit
{},// Default for add
{}// Default for delete
).navButtonAdd("#" + pager, {
caption : "Refresh",
buttonicon : "ui-icon-refresh",
onClickButton : function() {
var urlStr = getLastUrl(gridUrl);
jQuery("#" + gridName).jqGrid('setGridParam', {
url : urlStr,
mtype : 'POST',
datatype : 'json'
}).trigger("reloadGrid");
return true;
}
}).navButtonAdd("#" + pager, {
caption : "Export",
buttonicon : "ui-icon-save",
onClickButton : function() {
}
});
When grid is loading the button are displaying fine based on the logic, but after pagination buttons are not displaying in grid.
Not able to understand what happen. How to solve this issue?
I am using
jqGrid 4.0.0 - jQuery Grid
If you really need to use retro version 4.0.0, which is dead since many years, then you can fix your code by usage
formatter: function (cellvalue, options, rowObject) {
// access the data of another column by column index or by column name "getStatus"
var status = $.isArray(rowObject) ? rowObject[8] : rowObject.getStatus;
return status === "Active" ? "<button class=\"resend\">Resend</button>" : "-";
}
I'd strictly recommend you to upgrade jqGrid to free jqGrid 4.14.0 and to more recent jQuery version (any version between 1.7.2 and 3.1.1). jqGrid 4.0.0 is 6 years old. It's released at the time of Chrome 10, Firefox 3.5 and IE8 (IE9 was just published for Vista). Now we have Chrome 57, Firefox 52, Edge 38, IE11. I point only on one problem described here, which describe real problem, which you have in jqGrid 4.0.0 in case of usage the current version of Chrome. If you use jqGrid 4.0.0 then you have to use retro versions of jQuery and jQuery UI too. because jqGrid 4.0.0 can be used with jQuery versions < 1.6.
The above code will work for free jqGrid (because of compatibility reasons), but the recommended usage would be the following:
formatter: function (cellvalue, options) {
var status = options.rowData.getStatus;
return status === "Active" ? "<button class=\"resend\">Resend</button>" : "-";
}
Finally I would recommend you to remove the following jqGrid options: multiselect: false, repeatitems: true, imgpath : "themes/basic/images", caption: "" which are either wrong or contain default values and to add gridview: true (which is default in free jqGrid, but not default in jqGrid 4.0.0). You can consider to use height: "auto" instead of height: 200 and to specify the height of the grid with respect of rowNum.
Related
I'm upgrading jqgrid to the latest stable build of free-jqgrid (4.15.2) and the grid always shows a right-side gap where the scollbar will never need to be. It appears as though some of the usage has changed since the last developer updated the library and might be ahead of the documentation. I've looked at other questions in SO and:
I've tried manually stylling the grid, which did not help and served only to complicate matters.
I've tried setting scrollOffset:0 (with and without a height set in both percentatge and a static int) and it has not removed the scrollbar area
Other helpful info:
* We're manually resizing the grid to it's container on resize event and on initial draw. This code seems to have little effect now
I'm seeing the unsightly gap every time i set up a grid in a similar fashion to the following:
var grid_data = {
altRows: true,
data: [],
datatype: 'local',
sortable: false,
width: (bodyWidth() - 14),
rowNum: 10000,
colNames: [],
ondblClickRow: function() {
onGridDblClickRow();
},
onSelectAll: function() {
onGridSelectAll();
},
gridComplete: function() {
doGridComplete();
}
},
onRightClickRow: function( rowId ) {
doRightClick(rowId);
}
},
onSelectRow: $.proxy( onGridSelectRow, this ),
colModel: column_info_array,
multiselect: true,
multiselectWidth: 22,
viewrecords: true,
height:'100%',
scrollOffset:0,
}
The following fiddle shows the same problem in more reduced code
http://jsfiddle.net/catbadger/mhvzerdg/8/
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.
I have two dataTable in my page and I have a method like below:
function ToDataTable()
{
$(".dataTable").css("width", "100%");
$(".dataTable").each(function ()
{
var $that = $(this);
/* Start of method */
function ToDataTableInternal()
{
var table = $that.DataTable({
responsive: {
details: { type: "column", target: -1 },
},
columnDefs: [{
className: "control", orderable: !1, targets: -1,
},
{ orderable: !1 }],
"paging": false,
"ordering": false,
"info": false,
"searching": false,
retrieve: true
});
}
/* End of method */
if ($that.is(":visible"))
{
ToDataTableInternal()
}
else
{
// Observe all invisible parents or table to trigger
// ToDataTableInternal method if made visible
var $arr = $(this).parentsUntil(":visible").filter(function ()
{
return $(this).css("display") === "none";
}).add($(this));
var observers = [];
$arr.each(function ()
{
var observer = new MutationObserver(function (mutations)
{
mutations.forEach(function (mutation)
{
if ((mutation.attributeName === 'style' ||
mutation.attributeName === 'class') &&
$that.is(":visible"))
{
ToDataTableInternal();
for (var i = 0; i < observers.length; i++)
{
// Disconnect observers
observers[i].disconnect();
}
}
});
});
observers.push(observer);
observer.observe(this, {
attributes: true
});
});
}
});
}
The reason I have this method is that when table's display is none, it really lags browser(especially IE, where I cannot do anything for minimum of 5 seconds) which is the reason of that I'm changing the table to DataTable after it made visible.
But the problem with calling methods individually is the second DataTable doesn't have the same settings which I passed on.(The first one has) Instead, second one has filters, paging, sort elements in it too.
If I call both at the same time, nothing out of ordinary happens. What may be the problem?
EDIT: I can't reproduce the same behaviour in fiddles.
There seems to be no problems in another environments when I'm trying to do the same thing.
An another library we use is causing problems and there is no problem with DataTable library.
you can add following properties of dataTable in your datatable configuration to remove filtering, pageing and sorting:
Datatable 1.9
"bPaginate":false, //Enable or disable pagination.
"bFilter": false, //Enable or disable filtering of data
"bLengthChange": false, //Enable or disable the size dropdown
"bSort": false, //Enable or disable sorting of columns.
"bInfo": false, //Enable or disable the table information display.
Update
Datatable 1.10
Option name update in datatable 1.10
bPaginate -> paging
bFilter -> searching
bLengthChange -> lengthChange
bSort -> ordering
bInfo -> info
I'm using Datatables with Scroller plugin and server-side loading. When data are loaded, header columns are resized and often (not always) don't fit to inside columns.
Picture of a situation (http://i.stack.imgur.com/J3zMz.png):
Relevant datatables setting code:
"sScrollY" : window.innerHeight - 270,
"bServerSide" : true,
"sDom" : "frtiS",
"bProcessing" : true,
"bDeferRender" : true,
"bAutoWidth" : true,
"oScroller" : {
"rowHeight" : 33,
"autoHeight" : false,
"serverWait" : 100
},
Is there any way how force header columns to always fit the content (and vice versa)?
Thanks.
try
$(window).load( function () {
$('#myTable').dataTable().fnAdjustColumnSizing( false );
} );
I am using flexigrid in a project and I would like to be able to keep the selected rows after the grid is refreshing. I asked the same question on the flexigrid discussion board and I got this answer:
Add a click handler, save the id if the row id of the row selected. On refresh completion, select the row again (if still present)
Not sure how to proceed on this, I don't even know how a function will look like, so that's why I don't have any code to start with.
If someone could point me in the right direction will be greatly appreciated.
Thanks,
Cristian.
Flexigrid adds a class called trSelected to selected rows, so whenever a click event happens on the grid you could just look for all the selected rows and save them in some way. Below is just a quick example of what you could do:
var selectedRows = new Array();
$('#myGrid').click(function() {
selectedRows = new Array();
$(this).find('tr.trSelected').each(function(i, selectedRow) {
selectedRows.push($(selectedRow));
});
});
I have done small code to keep multi-selection between pagination and also during refresh.
$("#searchPhonoList").flexigrid($.extend({}, flexigridAttrs, {
url: './rest/phono/search',
preProcess: formatSearchPhonoResults,
onSuccess: successSearchPhono,
onSubmit: submit,
method: 'GET',
dataType: 'json',
colModel : [
{display: 'titre', name: 'titre_brut', width : 240, sortable : true, align: 'left'},
{display: 'version', name: 'version_brut', width : 60, sortable : true, align: 'left'}
],
height: "auto",
sortname: "score",
sortorder: "desc",
showTableToggleBtn: false,
showToggleBtn: false,
singleSelect: false,
onToggleCol: false,
usepager: true,
title: "Liste des candidats",
resizable: true,
rp:20,
useRp: true
}));
var searchPhonoListSelection = new Array();
$('#searchPhonoList').click(function(event){
$(' tbody tr', this).each( function(){
var id = $(this).attr('id').substr(3);
if ( searchPhonoListSelection.indexOf(id) != -1 ) {
searchPhonoListSelection.splice(searchPhonoListSelection.indexOf(id), 1);
}
});
$('.trSelected', this).each( function(){
var id = $(this).attr('id').substr(3);
if ( searchPhonoListSelection.indexOf(id) == -1 ) {
searchPhonoListSelection.push(id);
}
});
});
function successSearchPhono() {
$("#searchPhonoList tbody tr").each( function() {
var id = $(this).attr('id').substr(3);
if ( searchPhonoListSelection.indexOf(id) != -1 ) {
$(this).addClass("trSelected");
}
});
}