In a custom button in my pager, I call grid.jqGrid("getGridParam", "data"), "data") to get all the data in the grid but it returns empty array. When I call grid.jqGrid("getGridParam", "data") in the loadComplete function, it still returns an empty array. However if I call grid.jqGrid('getRowData') it gives me the data I am looking for. See my code below.
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<link rel="stylesheet" type="text/css" media="screen" href="${pageContext.request.contextPath}/css/jquery-ui.min.css"/>
<link rel="stylesheet" type="text/css" media="screen" href="${pageContext.request.contextPath}/css/ui.jqgrid.css"/>
<!-- Overide css styling to ensure that calendar image is inline with text box -->
<style type="text/css">.ui-jqgrid .ui-search-table .ui-search-input > input,
.ui-jqgrid .ui-search-table .ui-search-input > select,
.ui-jqgrid .ui-search-table .ui-search-input > img {vertical-align: middle; display: inline-block;}
</style>
<script src="${pageContext.request.contextPath}/js/jquery-1.11.0.min.js" type="text/javascript"></script>
<script src="${pageContext.request.contextPath}/js/jquery-ui.min.js" type="text/javascript"></script>
<script src="${pageContext.request.contextPath}/js/grid.locale-en.js" type="text/javascript"></script>
<script src="${pageContext.request.contextPath}/js/jquery.jqGrid.min.js" type="text/javascript"></script>
<title>Trucks Overview</title>
<script type="text/javascript">
jQuery().ready(function () {
var grid = jQuery("#truck_grid");
var orderGridDialog = $('#truck_grid_dialog');
var gridData;
getUniqueNames = function(columnName) {
var texts = grid.jqGrid('getCol', columnName, false);
var uniqueTexts = [], textsLength = texts.length, text, i, textsMap = {};
for (i=0;i<textsLength;i++) {
text = texts[i];
if (text != undefined && textsMap[text] === undefined) {
// to test whether the texts is unique we place it in the map.
textsMap[text] = true;
uniqueTexts.push(text);
}
}
return uniqueTexts;
};
buildSearchSelect = function(uniqueNames) {
var values=":All";
$.each (uniqueNames, function() {
values += ";" + this + ":" + this;
});
return values;
};
setSearchSelect = function(columnName) {
grid.jqGrid('setColProp', columnName,
{ stype: 'select',
searchoptions: {
value:buildSearchSelect(getUniqueNames(columnName)),
sopt:['eq']
}
}
);
};
var initDateWithButton = function (elem) {
if (/^\d+%$/.test(elem.style.width)) {
// remove % from the searching toolbar
elem.style.width = '';
}
// to be able to use 'showOn' option of datepicker in advance searching dialog
// or in the editing we have to use setTimeout
setTimeout(function () {
$(elem).datepicker({
dateFormat: 'mm/dd/yy',
showOn: 'button',
changeYear: true,
changeMonth: true,
buttonImageOnly: true,
buttonImage: "images/calendar.gif",
buttonText: "Select date",
showButtonPanel: true,
onSelect: function (dateText, inst) {
inst.input.focus();
if (typeof (inst.id) === "string" && inst.id.substr(0, 3) === "gs_") {
$(inst.id).val(dateText);
grid[0].triggerToolbar();
}
else {
// to refresh the filter
$(inst).trigger("change");
}
}
});
}, 100);
};
grid.jqGrid({
url: '${pageContext.request.contextPath}/getTrucksJSONAction',
datatype: "json",
mtype: 'GET',
colNames: ['Truck ID', 'Status', 'Carrier Code', 'Date Created', 'Date Closed', 'T1 Status', 'Truck Arrived'],
colModel: [
{name: 'truckId', key:true, index: 'truckId', align: 'center', width: 100},
{name: 'status', index: 'status', align: 'center', width: 100},
{name: 'carrierName', index: 'carrierName', align: 'center', width: 100},
{name: 'createdDate', index: 'createdDate', align: 'center', width: 100},
{name: 'closedDate', index: 'closedDate', align: 'center', width: 100},
{name: 't1Status', sortable: false, align: 'center', width: 100, fixed: true,
formatter: function (celvalue) {
return celvalue ?
"<img src='http://www.clker.com/cliparts/q/j/I/0/8/d/green-circle-icon-md.png' alt='green light' style='width:15px;height:15px'/>" :
"<img src='http://www.iconsdb.com/icons/preview/red/circle-xxl.png' alt='red light' style='width:10px;height:10px'/>";
}} ,
{name: 'truckArrived', sortable: false, align: 'center', width: 100, fixed: true,
formatter: function (celvalue) {
return celvalue ?
"<img src='http://www.clker.com/cliparts/q/j/I/0/8/d/green-circle-icon-md.png' alt='green light' style='width:15px;height:15px'/>" :
"<img src='http://www.iconsdb.com/icons/preview/red/circle-xxl.png' alt='red light' style='width:10px;height:10px'/>";
}}
],
rowNum: 10,
height: 300,
autoheight: true,
autowidth: true,
rowList: [10, 20, 30],
pager: jQuery('#truck_grid_pager'),
sortname: 'truckId',
sortorder: "desc",
jsonReader: {
root: "records",
page: "page",
total: "total",
records: "rows",
repeatitems: false
},
viewrecords: true,
altRows: false,
gridview: true,
hidegrid: false,
multiselect:true,
recordtext: '',
emptyrecords: 'No Trucks',
forceFit: true,
caption: "Trucks Overview",
loadComplete: function() {
// Reload the grid after changing paginattion
var allRecords = grid.getGridParam('lastpage') * grid.getGridParam('records');
grid.jqGrid('setGridParam', {
recordtext: allRecords + ' Trucks(s) Found. Displaying {0} to {1}'});
$(this).trigger("reloadGrid");
async: false,
setSearchSelect('status');
setSearchSelect('carrierName');
grid.jqGrid('setColProp', 'truckId', {
searchoptions : {
sopt : [ 'bw' ],
dataInit : function(elem) {
$(elem).autocomplete({
source : getUniqueNames('truckId'),
delay : 0,
minLength : 0
});
}
}
});
grid.jqGrid('setColProp', 'createdDate', {
sorttype: 'date', editable: true,
editoptions: { dataInit: initDateWithButton, size: 8 },
searchoptions: {
sopt: ['eq', 'ne', 'lt', 'le', 'gt', 'ge'],
dataInit: initDateWithButton
}
});
gridData = $(this).jqGrid("getGridParam", "data");
grid.jqGrid('filterToolbar', {autoSearch: true});
},
}).navGrid('#truck_grid_pager', {edit: false, add: false, del: false, search: false, refresh: true})
.navButtonAdd('#truck_grid_pager', {caption:"Truck Arrived", buttonicon:"ui-icon-flag", position:"first", title:"Truck Arrived",
onClickButton: function(){
var i;
var data = grid.jqGrid("getGridParam", "data");
var selRowIds = grid.jqGrid('getGridParam', 'selarrrow');
for (i = 0; i < data.length; i++) {
if (selRowIds.indexOf(data[i].truckId) > -1) {
data[i].truckArrived = true;
}
}
grid.trigger("reloadGrid");
}
})
.navButtonAdd('#truck_grid_pager', {caption:"Ship Confirm", buttonicon:"ui-icon-circle-check", position:"first", title:"Ship Confirm",
onClickButton: function(){
alert("Ship has been confirmed");}
});
orderGridDialog.dialog({
autoOpen: false,
width: 1000,
height: 400,
draggable: false,
show: {
effect: "blind",
duration: 500
},
hide: {
effect: "blind",
duration: 250
},
close: function(event, ui){
orderGridDialog.text('Loading Grid...');
}
});
});
</script>
</head>
<body>
<table id="truck_grid"></table>
<div id="truck_grid_pager"></div>
<div id="truck_grid_dialog" title="Orders Overview">Loading...</div>
</body>
</html>
The problem happens in the last section of the code, namely:
.navButtonAdd('#truck_grid_pager', {caption:"Truck Arrived", buttonicon:"ui-icon-flag", position:"first", title:"Truck Arrived",
onClickButton: function(){
var i;
var data = grid.jqGrid("getGridParam", "data");
var selRowIds = grid.jqGrid('getGridParam', 'selarrrow');
for (i = 0; i < data.length; i++) {
if (selRowIds.indexOf(data[i].truckId) > -1) {
data[i].truckArrived = true;
}
}
grid.trigger("reloadGrid");
}
})
The second problem I have is when grid.trigger("reloadGrid") is called, the truckArrived icon is not changed from red to green as expected.
The internal parameter data will be used only if one uses datatype: "local". You use datatype: "json". It means that the server hold whole dataset only. The url: '${pageContext.request.contextPath}/getTrucksJSONAction' receive request for the page of sorted and filtered data. The server should implement sorting, filtering/sorting and paging.
There exists a special case: one use remote datatype ("json" or "xml"), but one uses loadonce: true parameter additionally. In the case the server should return all unfiltered data instead of providing the page of data. The returned data should be still sorted corresponds to sortname, sortorder parameter (which will be sent to the server as sidx and sord). jqGrid displays the first page of returned data, but it fills the internal data parameter with whole rows of data returned from the server. After the first loading of data jqGrid changes datatype to "local" and so the later sorting, paging and filtering of data will be like in case of datatype: "local". In the case yoou will be able to get all the data using grid.jqGrid("getGridParam", "data"), but you can do this of case after the data will be once loaded.
Related
I have jqgrid page with a lot of columns. Idea is to allow user choose columns and their order in table and save this order and column count in cookies. For this purposes I use $.jgrid.saveState() for saving and $.jgrid.loadState() for restoring jqgrid options from cookies. This methods works fine. But I don't want to save data to storage: only column order and filter. I tried option restoreData: false and storeData: false, but it didn't work.
Here the code of my jqgrid:
jQuery(function ($) {
var table = $("#table");
var pager = "#pager";
var search_panel = "#search";
var localization = globalLocale;
var colNames = [ "Mobile direction total time (sec)", "Mobile direction q-ty ", "Mobile time Percent",
"City direction total time (sec)", "City direction q-ty", 'City time Percent' ];
var exportToCsvBut = "Export to excell";
resizeToFitPageSize(table);
resizeOnSidebar(table);
$(function () {
var d = new Date();
var month = d.getMonth();
var day = d.getDate();
var year = d.getFullYear();
var defCurDate = moment().startOf('day').format('DD.MM.YYYY HH:mm:ss');
var defNextDate = moment().endOf('day').format('DD.MM.YYYY HH:mm:ss');
var from = $('#datetimepickerFrom');
var to = $('#datetimepickerTo');
if (from.val() === "" || to.val() === "") {
from.val(defCurDate);
to.val(defNextDate);
}
$("#datetimepickerFrom").datetimepicker({
dateFormat: 'dd.mm.yy',
timeFormat: 'HH:mm:ss',
defaultDate: new Date(year, month, day + 1, 00, 00),
onClose: function () {
beforeRefresh();
}
});
$("#datetimepickerTo").datetimepicker({
dateFormat: 'dd.mm.yy',
timeFormat: 'HH:mm:ss',
defaultDate: new Date(year, month, day + 1, 00, 00),
onClose: function () {
beforeRefresh();
}
});
defCurDate = $('#datetimepickerFrom').val();
defNextDate = $('#datetimepickerTo').val();
});
var initDate = function (elem) {
$(elem).datetimepicker({
dateFormat: 'd.m.Y H:i:s',
showButtonPanel: true
});
};
var template = {width: 160, fixed: true, align: 'center', editable: false, stype: 'text'};
var colModel = [
{
name: 'mobileDirectionTotalTime',
index: 'mobileDirectionTotalTime',
sortname: 'mobileDirectionTotalTime',
template: template,
formatter: nullFormatter,
sorttype: 'number'
},
{
name: 'mobileDirectionQty',
index: 'mobileDirectionQty',
sortname: 'mobileDirectionQty',
template: template,
formatter: nullFormatter,
sorttype: 'number'
},
{
name: 'mobileDirectionPercent',
index: 'mobileDirectionPercent',
sortname: 'mobileDirectionPercent',
width: 120,
fixed: true, align: 'center', editable: false,
template: "number",
sorttype: 'number'
},
{
name: 'cityDirectionTotalTime',
edittype: "custom",
sortname: 'cityDirectionTotalTime',
formatter: null,
sorttype: 'number'
},
{
name: 'cityDirectionQty',
index: 'cityDirectionQty',
sortname: 'cityDirectionQty',
template: template,
sorttype: 'number'
},
{
name: 'cityDirectionTimePercent',
index: 'cityDirectionTimePercent',
sortname: 'cityDirectionTimePercent',
template: template,
sorttype: 'number'
},
];
table.jqGrid({
url: URL_DATA,
datatype: "json",
jsonReader: {
repeatitems: true
},
height: 'auto',
colNames: colNames,
colModel: colModel,
shrinkToFit: false,
forceFit: true,
pager: pager,
toppager: true,
rowNum: 10,
rowList: [5, 10, 15, 20, 25, 30],
loadonce: true,
viewrecords: true,
storeNavOptions : true,
// navOptions: {reloadGridOptions: {fromServer: true}},
loadComplete: function () {
var table = this;
setTimeout(function () {
updatePagerIcons(table);
enableTooltips(table);
}, 0);
},
gridComplete: function () {
/*var idarray = table.jqGrid('getDataIDs');
if (idarray.length > 0) {
var firstid = table.jqGrid('getDataIDs')[0];
table.setSelection(firstid);
}*/
}
});
$(window).triggerHandler('resize.jqGrid');//trigger window resize to make the grid get the correct size
function beforeRefresh() {
var from = $('#datetimepickerFrom');
var to = $('#datetimepickerTo');
if (from.val() != null && from.val() != '' && to.val() != null && to.val() != '') {
resetFilter('table', 'globalSearchText');
table.jqGrid().setGridParam({datatype: 'json'}).setGridParam({url: URL_DATA + "?from=" + from.val() + "&to=" + to.val()}).trigger("reloadGrid")
if (from.val() === "" || to.val() === "") {
from.val(defCurDate);
to.val(defNextDate);
}
}
}
//navButtons
table.jqGrid('navGrid', pager,
{ //navbar options
cloneToTop: true,
edit: false,
add: false,
del: false,
search: true,
searchicon: 'ace-icon fa fa-search orange',
refresh: true,
beforeRefresh: function () {
var from = $('#datetimepickerFrom');
var to = $('#datetimepickerTo');
if (from.val() != null && from.val() != '' && to.val() != null && to.val() != '') {
resetFilter('table', 'globalSearchText');
table.jqGrid().setGridParam({datatype: 'json'}).setGridParam({url: URL_DATA + "?from=" + from.val() + "&to=" + to.val()}).trigger("reloadGrid")
if (from.val() === "" || to.val() === "") {
from.val(defCurDate);
to.val(defNextDate);
}
}
},
refreshicon: 'ace-icon fa fa fa-refresh green',
view: true,
viewicon: 'ace-icon fa fa-search-plus grey'
}, {}, {}, {},
{
multipleSearch: true,
searchOnEnter: true,
closeOnEscape: true,
multipleSearch: true,
closeAfterSearch: true
},
{
//view record form
recreateForm: true,
beforeShowForm: function (e) {
var form = $(e[0]);
form.closest('.ui-jqdialog').find('.ui-jqdialog-title').wrap('<div class="widget-header" />')
form.closest('div.ui-jqdialog').center();
}
}
);
addToolButton({
caption: "",
buttonicon: "ace-icon fa fa-calculator blue",
title: "Выбрать столбцы",
onClickButton: function () {
$(this).jqGrid('columnChooser',
{
width: 550,
msel_opts: {dividerLocation: 0.5}, modal: true
});
$("#colchooser_" + $.jgrid.jqID(this.id) + ' div.available>div.actions')
.prepend('<label style="float:left;position:relative;margin-left:0.6em;top:0.6em">Поиск:</label>');
}
}, table, pager);
addSearchField('table', 'globalSearchText');
$(window).triggerHandler('resize.jqGrid');
table.triggerHandler("jqGridAfterGridComplete");
destroyGrid(table);
$('#table')
.append($("<div style='margin-top: 10px'>" +
"<button id='savestate'>save state</button>" +"<button id='loadstate'>load state</button>" +
"</div>"));
$("#savestate").click(function(){
$.jgrid.saveState("table");
});
$("#loadstate").click(function(){
$.jgrid.loadState("table", {}, {});
})
});
document.addEventListener('contextmenu', function (e) {
e.preventDefault();
});
Here the view of table page:
After user press load state and save state it displays data which was before but not actual:
It just show data which was saved in localstorage.
If I add storeData: false it just diplayed table with no data and doens't load new data from server.
Can anyone help?
P.S In case someone will have the same problem:
$("#table").jqGrid().setGridParam({datatype:'json'}).setGridParam({url : URL_DATA}).trigger("reloadGrid"); after $.jgrid.loadState("table", '', { restoreData: false}); will load new data in loaded grid.
I recommend you to use restoreData: false in loadState and after this command to reload the grid with trigger by example
$("#loadstate").click(function(){
$.jgrid.loadState("table", '', { restoreData: false});
$("#table").trigger("reloadGrid");
});
This will reload fresh grid data from server with the current setting
var specificatonsData = [];
function initGridForTransactions(gridID, gridPagerID) {
var grid_selector = gridID;
var pager_selector = gridPagerID;
$(window).on('resize.jqGrid', function () {
$(grid_selector).jqGrid('setGridWidth', $("#page-wrapper").width());
})
var parent_column = $(grid_selector).closest('[class*="col-"]');
$(document).on('settings.ace.jqGrid', function (ev, event_name, collapsed) {
if (event_name === 'sidebar_collapsed' || event_name === 'main_container_fixed') {
setTimeout(function () {
$(grid_selector).jqGrid('setGridWidth', parent_column.width());
}, 0);
}
})
$(grid_selector).jqGrid({
data: specificatonsData,
datatype: "local",
colNames: ['Id','Specification', 'Abbreviation'],
colModel: [
{ name: 'Id', width: 80,key:true },
{ name: 'specification', index: 'Id', key: true, width: 300 },
{ name: 'abbreviation', width: 300 },
],
cmTemplate: { editable: true },
cellsubmit: 'clientArray',
editurl: 'clientArray',
viewrecords: true,
rowNum: 4000,
gridview: true,
rowList: [4000],
pager: pager_selector,
altRows: true,
loadonce: true,
multiselect: false,
multiboxonly: false,
sortname: 'Specification',
sortorder: "asc",
cellEdit: false,
iconSet: "fontAwesome",
onSelectRow: function (rowId, status, e) {
var dealerFeatures = $("#editor").text();
var selectedFeature = rowId;
selectedFeature = selectedFeature.replace(/(\s+)/, "(<[^>]+>)*$1(<[^>]+>)*");
var pattern = new RegExp("(" + selectedFeature + ")", "gi");
dealerFeatures = dealerFeatures.replace(pattern, "<mark>$1</mark>");
//dealerFeatures = dealerFeatures.replace(/(<mark>[^<>]*)((<[^>]+>)+)([^<>]*<\/mark>)/, "$1<mark>$2</mark>$4");
dealerFeatures = dealerFeatures.replace(/(<mark>[<>]*)((<[>]+>)+)([<>]*<\/mark>)/, "$1<mark>$2</mark>$4");
dealerFeatures = dealerFeatures.replace(/\n/g, '<br>\n');
$("#editor").html(dealerFeatures);
},
gridComplete: function () {
$(grid_selector).setColProp('Approve', { editoptions: { value: '' } });
},
loadComplete: function () {
var table = this;
setTimeout(function () {
updatePagerIcons(table);
enableTooltips(table);
}, 0);
},
}).navGrid(pager_selector, { edit: true, add: true, del: false },
{
url: '/Activity/SaveSpecification',
closeAfterAdd: true,
closeAfterEdit: true,
afterSubmit: function () {
getAbbrData();
return [true, '', ''];
}
});
jQuery(grid_selector).sortableRows();
function updatePagerIcons(table) {
var replacement =
{
'ui-icon-seek-first': 'ace-icon fa fa-angle-double-left bigger-140',
'ui-icon-seek-prev': 'ace-icon fa fa-angle-left bigger-140',
'ui-icon-seek-next': 'ace-icon fa fa-angle-right bigger-140',
'ui-icon-seek-end': 'ace-icon fa fa-angle-double-right bigger-140'
};
$('.ui-pg-table:not(.navtable) > tbody > tr > .ui-pg-button > .ui-icon').each(function () {
var icon = $(this);
var $class = $.trim(icon.attr('class').replace('ui-icon', ''));
if ($class in replacement) icon.attr('class', 'ui-icon ' + replacement[$class]);
})
}
function enableTooltips(table) {
$('.navtable .ui-pg-button').tooltip({ container: 'body' });
$(table).find('.ui-pg-div').tooltip({ container: 'body' });
}
$(document).one('ajaxloadstart.page', function (e) {
$(grid_selector).jqGrid('GridUnload');
$('.ui-jqdialog').remove();
});
}
I will save data to database only when I click on external Submit button.
When I click on edit button the data is showing in a popup and when I click on the save button the data is getting to the database and showing in the jqgrid.
But I have a new requirement where I have to show the data in the jqgrid when click on save button but should not save to the database.
Thanks in advance.
If you use Guriddo jqGrid JS then you can set url in edit options in your navigator to be clientArray - i.e
...navGrid(pager_selector, { edit: true, add: true, del: false },
{
url: 'clientArray',
closeAfterAdd: true,
closeAfterEdit: true,
afterSubmit: function () {
getAbbrData();
return [true, '', ''];
}
});
This will save the data locally.
The code, which you posted contains many small bugs. For example,
you use url: '/Activity/SaveSpecification' as form Edit options (not for Add form) - see navGrid call. You should remove the option to make editurl: 'clientArray' working
you use key:true in more as one column. It's not allowed. One can use it only in one column, which contains unique values.
the usage of index: 'Id' property in colModel for the column name: 'specification' is probably one more bug, which can make wrong sorting and filtering in the column.
your current code contains call of .setColProp('Approve', { ... });, which is wrong, because your colModel don't contains the column 'Approve'
the option sortname: 'Specification' is wrong too, because the value of sortname should be the value of name property from colModel (like sortname: 'specification' for example, if you'll remove index: 'Id' property from the column).
Additionally the usage of rowNum: 4000 can essentially reduce the performance of the grid in case of large grid. If real number of rows is about 4000, then it's much more effective to use local paging of data. The monitor allows to display only about 20-25 rows. Thus it's recommended to use pager with such small rowNum. Users can use paging buttons to go to the next page.
Hi I have a Grid that is using cell edit and Inline editing. It saves to the ClientArray
$('#list').jqGrid({
datatype: "local",
colNames: ["Parameter Id", "Parameter Name", 'Parameter Value'],
colModel: [
{ name: "Id", index: "Id", align: "left", key: true, editable: false,hidden:true, jmap: 0 },
{ name: "ParameterName", index: "ParameterName", align: "left", editable: false, jmap: 1 },
{ name: "ParameterValue", index: "ParameterValue", align: "left", editable: true, edittype: "text", editoptions: { maxlength: 100 }, editrules: {required: true }, jmap: 2 }
],
pager: "#pager",
rowNum: 100,
rowList: [],
pgbuttons: false, // disable page control like next, back button
pgtext: null, // disable pager text like 'Page 0 of 10'
viewrecords: true, // disable current view record text like 'View 1-10 of 100'
height: '100%',
scrollOffset: 0,
sortname: "Name",
sortorder: "Asc",
gridview: true,
caption: 'Parameters',
autowidth: true,
hidegrid: false,
loadonce: true,
//beforeEditCell: function () {
// $("#list_ilsave").removeClass('ui-state-disabled');
// return;
//},
//afterEditCell: function (rowid, cellname, value, iRow, iCol) {
// $('#list').jqGrid('getCell', rowid, iCol).focus();
// return;
//},
width: totalWidth,
cellEdit: true,
cellsubmit: "clientArray"
});
$('#list').jqGrid('inlineNav', '#pager', {
edit: false,
add: false,
del: false,
save: true,
savetext: 'Save',
cancel: false
});
When I edit a Cell the save button remains disabled. If I manually Enable the button in beforeCellEdit, the editable cell hasn't got focus until you select another cell. This behavior is only happening in IE.
I have tried to fix both these issues individually in my commented out code, and I have found that the loss of focus is caused by the line
$("#list_ilsave").removeClass('ui-state-disabled');
I tried placing this line in beforeEditCell and in afterEditCell and it causes the input field to loose focus.
I was using JQ Grid 4.4.4 and I have tried updating to 4.6.0 after I read there were updates to Inline Editing after 4.4.4
UPDATE
I have changed my grid to use onSelectRow
onSelectRow: function (rowid) {
var $grid = $('#list');
var iRow = $("#" + rowid)[0].rowIndex;
$grid.jqGrid('editRow', rowid, {
keys: true,
oneditfunc: function(rowid, response) {
var $saveButton = $("#list_ilsave");
if ($saveButton.hasClass('ui-state-disabled')) {
$saveButton.removeClass('ui-state-disabled');
}
markCellAsDirty(rowid, $grid);
return true;
},
successfunc: function() {
alert('success');
return true;
},
aftersavefunc: function() {
alert('after save');
return true;
},
errorfunc: function() {
alert('error');
return true;
}
});
},
cellsubmit: "clientArray"
But I can't get any of the editRow events to fire other than oneditfunc. I also have an issue with getting the changed cells.
This method marks the cells as dirty / edited
function markCellAsDirty(rowid, grid) {
$(grid.jqGrid("setCell", rowid, "ParameterValue", "", "dirty-cell"));
$(grid[0].rows.namedItem(rowid)).addClass("edited");
}
I try to get the edited cells as follows
var editedRows = $grid.getChangedCells('dirty');
Before posting editedRows in an AJAX method to my server.
I'm not sure what you want to implement exactly, but I modified your demo to the following https://jsfiddle.net/OlegKi/byygepy3/11/. I include the full JavaScript code of the demo below
$(function () {
var myData = [
{ id: 10, ParameterName: "Test", ParameterValue: "" },
{ id: 20, ParameterName: "Test 1", ParameterValue: "" },
{ id: 30, ParameterName: "Test 2", ParameterValue: "" }
],
$grid = $("#list");
// change the text displayed on editrules: {required: true }
$.extend(true, $.jgrid.locales["en-US"].edit.msg, {
required: "No value was entered for this parameter!!!"
});
$grid.jqGrid({
datatype: "local",
data: myData,
colNames: ["", "Parameter Name", "Parameter Value"],
colModel: [
{ name: "act", template: "actions" }, // optional feature
{ name: "ParameterName" },
{ name: "ParameterValue", editable: true,
editoptions: { maxlength: 100 }, editrules: {required: true } }
],
cmTemplate: { autoResizable: true },
autoResizing: { compact: true },
pager: true,
pgbuttons: false, // disable page control like next, back button
pgtext: null, // disable pager text like 'Page 0 of 10'
viewrecords: true, // disable current view record text like 'View 1-10 of 100'
sortname: "Name",
iconSet: "fontAwesome",
caption: 'Parameters',
autowidth: true,
hidegrid: false,
inlineEditing: {
keys: true
},
singleSelectClickMode: "selectonly", // prevent unselect once selected rows
beforeSelectRow: function (rowid) {
var $self = $(this), i,
// savedRows array is not empty if some row is in inline editing mode
savedRows = $self.jqGrid("getGridParam", "savedRow");
for (i = 0; i < savedRows.length; i++) {
if (savedRows[i].id !== rowid) {
// save currently editing row
// one can replace saveRow to restoreRow in the next line
$self.jqGrid("saveRow", savedRows[i].id);
}
}
return savedRows.length === 0; // allow selection if saving successful
},
onSelectRow: function (rowid) {
$(this).jqGrid("editRow", rowid);
},
afterSetRow: function (options) {
var item = $(this).jqGrid("getLocalRow", options.rowid);
if (item != null) {
item.dirty = true;
}
},
navOptions: {
edit: false,
add: false,
search: false,
deltext: "Delete",
refreshtext: "Refresh"
},
inlineNavOptions: {
save: true,
savetext: "Save",
cancel: false,
restoreAfterSelect: false
},
formDeleting: {
// delete options
url: window.g_baseUrl + 'MfgTransactions_MVC/COA/Delete?',
beforeSubmit: function () {
// get value
var selRowId = $(this).jqGrid('getGridParam', 'selrow');
var parametricValue = $(this).jqGrid('getCell', selRowId, 'ParameterValue');
// check if empty
if (parametricValue === "") {
return [false, "Cannot delete: No value exists for this parameter"];
}
return [true, "Successfully deleted"];
},
delData: {
batchId: function () {
return $("#BatchId").val();
}
},
closeOnEscape: true,
closeAfterDelete: true,
width: 400,
msg: "Are you sure you want to delete the Parameter?",
afterComplete: function (response) {
if (response.responseText) {
alert("response.responseText");
}
//loadBatchListIntoGrid();
}
}
}).jqGrid('navGrid')
.jqGrid('inlineNav')
.jqGrid('navButtonAdd', {
caption: "Save Changed",
buttonicon: "fa-floppy-o",
onClickButton: function () {
var localData = $(this).jqGrid("getGridParam", "data"),
dirtyData = $.grep(localData, function (item) {
return item.dirty;
});
alert(dirtyData.length > 0 ? JSON.stringify(dirtyData) : "no dirty data");
}
});
// make more place for navigator buttons be rwducing the width of the right part
var pagerIdSelector = $grid.jqGrid("getGridParam", "pager");
$(pagerIdSelector + "_right").width(100);
// make the grid responsive
$(window).bind("resize", function () {
$grid.jqGrid("setGridWidth", $grid.closest(".container-fluid").width());
}).triggerHandler("resize");
});
where HTML code is
<div class="container-fluid">
<div class="row">
<div id="gridarea" class="col-md-6 col-md-offset-3">
<table id="list"></table>
</div>
</div>
</div>
and CSS code
.ui-th-column>div, .ui-jqgrid-btable .jqgrow>td {
word-wrap: break-word; /* IE 5.5+ and CSS3 */
white-space: pre-wrap; /* CSS3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
overflow: hidden;
vertical-align: middle;
}
It demonstrate how one can implement starting inline editing on select row. Additionally I added optional column with template: "actions" which can be alternative implementation. I set property dirty in every item of data inside of afterSetRow callback and I added "Save Changed" button, which uses localData = $(this).jqGrid("getGridParam", "data") and dirtyData = $.grep(localData, function (item) { return item.dirty; }); to get the dirty (modified) data.
I need to have an editype checkmark column where when checkmark is checked today's date automatically is added next to checkmark and after submit to cell and if unchecked the date is removed on editform and on submit sends "null" to leave cell empty. I know I can use use
{ name: 'MyCol', index: 'MyCol', editable:true, edittype:'checkbox', editoptions: { value:"True:False" }
But I have no idea how to display the date next to the checkbox(like pic)and then add that date to cell on submit. Help please.
My code as it currently as it exists UPDATED with answer:
`
<title>PWe</title>
<link rel="stylesheet" type="text/css" media="screen" href="css/jquery-ui-1.10.3.custom.min.css" />
<link rel="stylesheet" type="text/css" media="screen" href="css/ui.jqgrid.css" />
<link rel="stylesheet" type="text/css" media="screen" href="css/nhf.css" />
<script src="js/jquery-1.9.0.min.js" type="text/javascript"></script>
<script src="js/i18n/grid.locale-en.js" type="text/javascript"></script>
<script src="js/jquery.jqGrid.min.js" type="text/javascript"></script>
<script src="js/jquery-ui-1.10.3.custom.js" type="text/javascript"></script>
<script src="http://code.jquery.com/jquery-migrate-1.2.1.js"></script>
<script type="text/javascript">
$(function(){
$("#list").jqGrid({
url:'request.php',
editurl: "jqGridCrud.php",
datatype: 'xml',
mtype: 'GET',
height: 'AUTO',
width: 900,
scrollOffset:0,
hidegrid: false,
colNames:['id','Project', 'Assigned To','Dev','Approve','Due Date','Attachments','Notes','App','mydate2',""],
colModel :[
{name:'id', index:'id', width:28, align: 'center'},
{name:'name', index:'name', width:170, align:'left',editable:true, editoptions:{
size:60} },
{name:'id_continent', index:'id_continent', width:50, align:'right',editable:true,edittype:'select',
editoptions:{value: "Henry:Henry; Ramon:Ramon; Paul:Paul" },mtype:'POST' },
{name:'lastvisit', index:'lastvisit', width:55, align:'right',formatter: 'date',srcformat:'yyyy-mm-dd',newformat: 'm/d/yy',editable:true, edittype: 'text',mtype:'POST' , editoptions:{size:10, dataInit:function(elem){$(elem).datepicker({dateFormat:'m/d/yy'});}}} ,
{name:'cdate', index:'cdate', width:55, align:'right',formatter: 'date',srcformat:'yyyy-mm-dd',newformat: 'm/d/yy', edittype: 'text',editable:true ,mtype:'POST' ,editoptions:{size:10, dataInit:function(elem){$(elem).datepicker({dateFormat:'m/d/yy'});}}} ,
{name:'ddate', index:'ddate', width:55, align:'right',formatter: 'date',srcformat:'yyyy-mm-dd',newformat: 'm/d/yy',date:'true',editable:true, edittype: 'text',editoptions:{size:10, dataInit:function(elem){$(elem).datepicker({dateFormat:'m/d/yy'});}}} ,
{name:'email', index:'email', width:50,align:'center',sortable:false,mtype:'POST',formatter:function(cellvalue, options, rowObject) {
if (cellvalue === undefined || cellvalue === null || cellvalue === 'NULL') {
return ''; // or just ""
}
return '<img src="file.png"> ';
}},
{name:'notes', index:'notes', width:100, align:'left',sortable:false, editable:true,edittype:'textarea',formatter:'link', editoptions:{
rows:10,cols:60} },
{ name: "hello", index:'hello',width: 17, align: "right", formatter: "checkbox",
editable: true,
edittype: "checkbox",
editoptions: {
value: "Yes:No",
defaultValue: "Yes",
dataEvents: [
{
type: "change",
data: { uncheckedDate: "" },
fn: function (e) {
if ($(this).is(':checked')) {
var date = new Date(Date.now()),
strDate = (date.getMonth() + 1) + "/" +
date.getDate() + "/" +
date.getFullYear();
$("#mydate").text(strDate);
} else {
$("#mydate").text(e.data.uncheckedDate);
}
}
}
]
}},
{name:'mydate2', index:'mydate2', width:40, align:'left',formatter: 'date',srcformat:'yyyy-mm-dd',newformat: 'm/d/yy',date:'true',editable:false} ,
{name:'act',index:'act',width:30 ,align:'left', sortable:false,formatter: "actions",cellattr: function () { return ' title="Delete Project"'; },
formatoptions: {
keys: true,
deltitle: 'delete',
delbutton: true,
editbutton:false,
delOptions: {
url: 'delete-perm.php',
afterShowForm: function ($form) {
$("#dData", $form.parent()).click();
},
msg: "Remove Selected Project?",
bSubmit: "Remove",
bCancel: "Cancel"
}
}},
],
pager: '#pager',
rowNum:30,
rowList:[30,40,80],
sortname: 'ddate',
sortorder: 'asc',
viewrecords: true,
gridview: true,
caption: 'Current Assignments',
ondblClickRow: function(rowid) {
$(this).jqGrid('editGridRow', rowid,
{width:550,Height:550,recreateForm:true,closeAfterEdit:true,
closeOnEscape:true,reloadAfterSubmit:true, modal:true,mtype:'post',top:350,left: 30});}
});
jQuery.extend(jQuery.jgrid.nav, {
deltitle: '',
delcaption: 'Project Complete'
},{delicon: "ui-icon-circle-check",deltext: "Project Complete"});
$("#list").jqGrid("navGrid", "#pager", { add: false, search: false, refresh:false,edit:false }).navButtonAdd('#pager',{
caption:"Export to Excel",
buttonicon:"ui-icon-save",
onClickButton: function () {
jQuery("#list").jqGrid('excelExport', { url: 'ExportExcel.php' });
},
position:"last",
});
jQuery.extend(jQuery.jgrid.edit, {
recreateForm: true,
beforeShowForm: function ($form) {
$("<span id='mydate'></span>").insertAfter("#hello");
$("#hello").trigger("change"); // to set date
},
onclickSubmit: function () {
return {
mydate2: $("#mydate").text()
}
},
afterclickPgButtons: function () {
$("#hello").trigger("change"); // to set date
} });
// setup grid print capability. Add print button to navigation bar and bind to click.
setPrintGrid('list','pager','Current Assignments');
});
There are many ways to implement your requirements. The first one is the usage of edittype: "custom". It allows you to create any editing element in edit form. The same approach work in inline editing or in Searching dialog. The demo from the answer and this old one describes all more detailed.
Another way is more easy. One can just add one more control, for example <span> after the checkbox. One can fill the span and change it based on changes of the chackbox. The demo demonstrates the approach. The most important part of the code is the following:
The grid have the editable column "closed" with edittype: "checkbox". I use form editing to edit the grid. Form editing creates editing controls which ids are the same as the value of name property. So the checkbox for editing the column "closed" in the edit form will have the id="closed". Inside of beforeShowForm callback I insert additional <span> element with id="mydate" directly after the checkbox "closed":
beforeShowForm: function () {
$("<span id='mydate'></span>").insertAfter("#closed");
// we trigger change event on the chechbox only to execute once
// the custom event handler which fills the span #mydate
$("#closed").trigger("change");
}
The definition of the column "closed" of the grid contains editoptions.dataEvents which defines the handler of "change" event. The event handler fills the span with id="mydate" based on the state of the checkbox:
colModel: [
...
{ name: "closed", width: 70, align: "center", formatter: "checkbox",
editable: true,
edittype: "checkbox",
editoptions: {
value: "Yes:No",
defaultValue: "Yes",
dataEvents: [
{
type: "change",
data: { uncheckedDate: "9/11/1964" },
fn: function (e) {
if ($(this).is(':checked')) {
var date = new Date(Date.now()),
strDate = (date.getMonth() + 1) + "/" +
date.getDate() + "/" +
date.getFullYear();
$("#mydate").text(strDate);
} else {
$("#mydate").text(e.data.uncheckedDate);
}
}
}
]
},
stype: "select",
searchoptions: {
sopt: ["eq", "ne"],
value: ":Any;true:Yes;false:No"
}
},
As the result the form looks like on the picture below
Additional editing callback
afterclickPgButtons: function () {
$("#closed").trigger("change"); // to set date
}
refreshes the date new the checkbox after the user clicks next/previous record button.
To send additional data with the data from madate <span> I used onclickSubmit callback
onclickSubmit: function () {
return {
myDate: $("#mydate").text()
}
}
which send the date as myDate parameter during submitting of editing form.
I have a jqGrid that allows inline editing/adding of data. When a user double clicks on the row, inline edit starts. When the user presses enter or clicks on another row, I want the changes to be saved. For some reason, however, the row is being restored before the saveRow function is being called and my edits are not saved (the AJAX call never happens).
My code is shown below. When I press the enter key, my changes are saved and sent to the server. When I click on another row, my changes are not sent to the server (no AJAX call) and I see in the console that afterrestorefunc is called before the saveEdit.
var editParams = {
afterSubmit: processResponse,
successfunc: function(response) {
var processed = processResponse(response);
if(processed[0] !== true) {
$.jgrid.info_dialog($.jgrid.errors.errcap, processed[1], $.jgrid.edit.bClose);
}
return processed[0];
},
afterrestorefunc: function(id) {
console.log('afterrestorefunc - ' + id);
},
bottominfo: 'Fields marked with an (*) are required',
keys: true
},
zipEditParams = $.extend(true, {}, editParams, {url: 'editdata.php'});
/* Set global default options */
$.extend($.jgrid.defaults, {
grouping: true,
shrinkToFit: false,
rowList: [10, 20, 30, 40, 50, 100],
rowNum: 20,
repeatitems: false,
ondblClickRow: inlineEdit,
onSelectRow: saveEdit
});
$('#zipcodes')
.jqGrid({
datatype: 'json',
colNames: ['Zip', 'City', 'State', 'Country'],
colModel: [
{name: 'zip_zip', jsonmap: 'zip_zip', width: 75, editable: true, editrules: {required: true}, formoptions: {elmprefix: '(*) '}},
{name: 'zip_city', jsonmap: 'zip_city', width: 75, editable: true, editrules: {required: true}, formoptions: {elmprefix: '(*) '}},
{name: 'zip_state', jsonmap: 'zip_state', width: 75, editable: true, editrules: {required: true}, formoptions: {elmprefix: '(*) '}},
{name: 'zip_country', jsonmap: 'zip_country', width: 75, editable: true, editrules: {required: true}, formoptions: {elmprefix: '(*) '}}
],
height: 200,
ignoreCase: true,
jsonReader: { repeatitems: false, id: 'zip_zip' },
pager: '#zipcodes_pager',
url: 'data.php',
editurl: 'editdata.php'
})
.jqGrid('navGrid', '#zipcodes_pager', {add: false, edit: false, del: false, refresh: false, search: false})
.jqGrid('inlineNav', '#zipcodes_pager', {edit: true, save: true, cancel: false, editParams: zipEditParams});
var lastSel;
/* Start editing the row */
function inlineEdit(id, iRow, iCol) {
var editParams = this.id == 'zipcodes' ? zipEditParams : (this.id == 'labels' ? labelEditParams : (this.id == 'users' ? userEditParams : {}));
$(this).jqGrid('editRow', id, editParams);
focusRow(id, iCol, this);
}
function focusRow(id, iCol, table) {
var ele = document.getElementById(id + '_' + table.p.colModel[iCol].name),
length = ele.value.length;
ele.focus();
if(ele.setSelectionRange) { //IE
ele.setSelectionRange(length, length);
}
else if(ele.createTextRange) {
var range = ele.createTextRange();
range.collapse(true);
range.moveEnd('character', length);
range.moveStart('character', start);
range.select();
}
}
function saveEdit(id) {
if(id && id != lastSel) {
console.log('saveRow: ' + this.id + ' - ' + lastSel);
/* Save the last selected row before changing it */
var saveParams = zipEditParams;
$(this).jqGrid('saveRow', lastSel, saveParams);
lastSel = id;
}
}
function processResponse(response) {
console.log('processResponse');
var obj = $.parseJSON(response.responseText),
retVal = true,
message = '',
new_id = '';
if(obj.message) {
if(obj.message == 'not logged in') {
location.href = 'logout.php';
}
else if(obj.message != 'true') {
message = obj.message;
retVal = false;
}
}
return [retVal, message, new_id];
}
Any help with this problem is greatly appreciated.
UPDATE It seems that if I comment out .jqGrid('inlineNav', '#zipcodes_pager', {edit: true, save: true, cancel: false, editParams: zipEditParams});, then everything works as expected. I also tried just using .jqGrid('inlineNav', '#zipcodes_pager');, but saw the same results. This is nice and could work in the short term, but I still would like the functionality of inline adding if possible.
i think you need to add more functionality to your onSelectRow function
onSelectRow: function (id) {
if (id && id !== lastsel) {
// cancel editing of the previous selected row if it was in editing state.
// jqGrid hold intern savedRow array inside of jqGrid object,
// so it is safe to call restoreRow method with any id parameter
// if jqGrid not in editing state
if (typeof lastsel !== "undefined") {
jQuery("#grid").jqGrid('restoreRow', lastsel);
}
lastSel = id;
}
},
in this code i'm not doing editing on selecting the row, but you can see that you need to restore the previous selected row, if that row was in edit mode and you click on some other row.
Try this.