Here is example code for what I'm doing if it helps.
var griditemobj = {
title: "<B>Event Editor</B>",
height: 'calc(100% - 55px)',
allowInvalid: true,
rowBorders: true,
columnBorders: true,
stripeRows : false,
resizable: true,
collapsible: { on: false, toggle: false , css: { margin: "50px 0 55px 200px" }},//toggled: true,
editor: { select: true },
numberCell: { show: true },
scrollModel: { autofit: true },
swipeModel: { on: true },
trackModel: { on: true }, //to turn on the track changes.
filterModel: { header: true, type: 'local', menuIcon: true },
sortModel: { single: false, multiKey: 'shiftKey' },
cellKeyDown: function( event, ui ) {
var nextrow = ui.rowIndx;
var nextcol = ui.colIndx;
// deal with add row with tab at last cell
var totalRecords = this.option('dataModel.data').length - 1;
var totalcolumns = this.getColModel().length - 1;
if (event.keyCode == 9 && ui.rowIndx == totalRecords && ui.colIndx == totalcolumns ) {
var dt = new Date();
var usetime = dt.getHours() + ":" + dt.getMinutes().toString().padStart(2, '0') ;
var rowData = { griditemnumber: 0, commandid: "6", command: "First", movestatusid: 1, status: "New", startdate: jsstartdate, starttime: usetime, iskey: false}; //new row initial contents
var newrow = addRowLocal(rowData);
}
},
toolbar: {
items: [
{ type: 'button', icon: 'ui-icon-plus', label: 'New', listener:
{ "click": function (evt, ui) {
var dt = new Date();
var usetime = dt.getHours() + ":" + dt.getMinutes().toString().padStart(2, '0') ;
var rowData = { filename: '&', griditemnumber: GLOBAL.nextnum, commandid: "6", command: "Contextual", statusid: 1, status: "Pending", startdate: jsstartdate, starttime: usetime, modeid: 1, modewhat: "New", iskey: false }; //new row initial contents
var returnval = addRowLocal(rowData);
}
}
},
{ type: 'separator' },
{ type: 'button', icon: 'ui-icon-disk', label: 'Save', cls: 'changes', listener:
{ "click": function (evt, ui) {
savegriditemChanges();
}
},
options: { disabled: true }
},
{ type: 'separator' },
{
type: 'button', icon: 'ui-icon-arrowreturn-1-s', label: 'Undo', cls: 'changes', listener: function () {
this.history({ method: 'undo' });
},
options: { disabled: true }
},
{
type: 'button', icon: 'ui-icon-arrowrefresh-1-s', label: 'Redo', listener: function () {
this.history({ method: 'redo' });
},
options: { disabled: true }
}
]
},
history: function (evt, ui) {
var $tb = this.toolbar();
if (ui.canUndo != null) {
$("button.changes", $tb).button("option", { disabled: !ui.canUndo });
}
if (ui.canRedo != null) {
$("button:contains('Redo')", $tb).button("option", "disabled", !ui.canRedo);
}
$("button:contains('Undo')", $tb).button("option", { label: 'Undo (' + ui.num_undo + ')' });
$("button:contains('Redo')", $tb).button("option", { label: 'Redo (' + ui.num_redo + ')' });
},
colModel: [
{ title: "ID", dataType: "integer", dataIndx: "moveid", editable: true, hidden: true},
{ title: "#", minWidth: 50, maxWidth: 60, dataType: "string", align: "center", dataIndx: "griditemnumber", editable: true, hidden: false,
render: function (ui) {
var cellData = ui.cellData;
if (!cellData) {
return {cls: 'pq-cell-blue-tr'};
}
},
filter: { menuIcon: false },
},
{ title: "Key", type: "checkbox", minWidth: 40, maxWidth: 40, dataType: "bool", align: "center", dataIndx: 'iskey', editor: true,
cb: {all: false, header: false},
filter: { crules: [{ condition: "equal" }] }
},
{ title: "Date", minWidth: 75, maxWidth: 90, align: "center", editable: true, dataIndx: "startdate", dataType: 'date',
editor: {
type: 'textbox',
init: dateEditor
},
render: function (ui) {
var cellData = ui.cellData;
if (cellData) {
return $.datepicker.formatDate('m/d/y', new Date(cellData));
} else {
return {cls: 'pq-cell-blue-tr'};
}
},
validations: [
{ type: 'regexp', value: '^([0]?[1-9]|[1][0-2])[./-]([0]?[1-9]|[1|2][0-9]|[3][0|1])[./-]([0-9]{4}|[0-9]{2})$', msg: 'Not in m/d/yy format' },//, warn: true
],
filter: { menuIcon: false }
},
{ title: "Time", minWidth: 60, maxWidth: 75, align: "center", dataType: "string", dataIndx: "starttime",
render: function (ui) {
var cellData = ui.cellData;
if (!cellData) {
return {cls: 'pq-cell-blue-tr'};
}
},
validations: [
{ type: 'regexp', value: '^(([0-9])|([0-1][0-9])|([2][0-3])):?([0-5][0-9])$', msg: 'Not in HH:MM format' }
],
filter: { menuIcon: false }
},
{ dataIndx: "commandid", hidden: true },
{ title: "Type", minWidth: 90, maxWidth: 100, dataIndx: "command",
editor: {
type: 'select',
options: arrCommands,
valueIndx: "commandid",
labelIndx: "command"
},
render: function (ui) {
var cellData = ui.cellData;
if (!cellData) {
return {cls: 'pq-cell-blue-tr'};
}
},
filter: { crules: [{ condition: 'contain'}], listeners: ['keyup'] }
},
{ dataIndx: 'fromuserid', hidden: true }, //hidden column to store Id.
{ title: "From", minWidth: 150, dataIndx: "fromusername",
editor: {
type: 'select',
options: arrfromusers,
valueIndx: "fromuserid",
labelIndx: "fromusername"
},
render: function (ui) {
var cellData = ui.cellData;
if (!cellData) {
return {cls: 'pq-cell-blue-tr'};
}
},
filter: { crules: [{ condition: 'contain'}], listeners: ['keyup'] }
},
{ dataIndx: "touserid", hidden: true },
{ title: "To", minWidth: 150, dataIndx: "tousername",
editor: {
type: 'select',
options: arrtousers,
valueIndx: "touserid",
labelIndx: "tousername"
},
render: function (ui) {
var cellData = ui.cellData;
if (!cellData) {
return {cls: 'pq-cell-blue-tr'};
}
},
filter: { crules: [{ condition: 'contain'}], listeners: ['keyup'] }
},
{ title: "Subject", minWidth: 200, dataType: "string", dataIndx: "namefield",
editor: {
type: 'textarea', attr:'rows=3'
},
render: function (ui) {
var cellData = ui.cellData;
if (!cellData) {
return {cls: 'pq-cell-blue-tr'};
}
},
filter: { crules: [{ condition: 'contain'}], listeners: ['keyup'] }
},
{ dataIndx: "modeid", hidden: true },
{ title: "Mode", minWidth: 80, maxWidth: 90, dataIndx: "modewhat",
editor: {
type: 'select',
options: arrmode,
valueIndx: "modeid",
labelIndx: "mode"
},
filter: { crules: [{ condition: 'contain'}], listeners: ['keyup'] }
},
{ title: "", editable: false, minWidth: 40, maxWidth: 40, width: 40, align: "center", sortable: false, title: "Del", dataIndx: "Del",
render: function (ui) {
return "<button type='button' class='ui-button ui-corner-all ui-state-default ui-button-icon-only delete_btn'><span class='ui-icon ui-icon-trash'></span></button>";
},
postRender: function (ui) {
var grid = this,
$cell = grid.getCell(ui);
$cell.find(".delete_btn")
.bind("click", function (evt) {
$griditemgrid.addClass({ rowIndx: ui.rowIndx, cls: 'pq-row-delete' });
var ans = window.confirm("Are you sure to delete griditem Number " + ui.rowData.griditemnumber + "?");
if (ans) {
$griditemgrid.deleteRow({ rowIndx: ui.rowIndx });
}
else {
$griditemgrid.removeClass({ rowIndx: ui.rowIndx, cls: 'pq-row-delete' });
}
});
},
filter: { menuIcon: false }
}
],
postRenderInterval: -1, //call postRender synchronously.
dataModel: {
dataType: "JSON",
sorting: "local",
sortIndx: "startdate",
sortDir: "up",
location: "remote",
recIndx: "moveid",
url: "/url/&returnFormat=json",
getData: function (response) {
return { data: response };
}
}
};
var $griditemgrid = pq.grid("#griditem_editing", griditemobj);