I'm am new to jqGrid. I am trying to implement a jqGrid that is populated with data returned by a REST call and several checkboxes that a user can edit to upload a new object to the DB using another rest call. I am having trouble populating the grid.
The issue I am experiencing is that the grid seems to take up the vertical space on the page, but is not displaying any information. The headers of the grid displayed fine when I just had a grid with no data.
During debug with Chrome, I found that the properties I expected to be returned from the row object when evaluated in the console are not there, ie. they are undefined.
Here is the code I am using:
var RGrid = [];
$.ajax({
url: restApi + EndPoint + '/' + Number,
type: 'GET',
success: function (response) {
Object2 = response;
var rData = $('#ResGrid').jqGrid().getRowData();
for (var i = 0; i < Object2.Requests.length; i++) {
var existingRows = rData.filter(function (a) {
return a.rId == Object2.Requests[i].Resource.Id;
});
if (existingRows.length == 0) {
var newObj = {
a: Object2.Requests[i].Resource.Name,
e: Object2.Requests[i].Resource.Id,
f: Object2.Requests[i].Id,
d: false,
b: false,
c: false
};
RGrid.push(newObj);
$('#ResGrid').jqGrid('addRowData', 1, newObj);
}
}
},
error: function (textStatus) {
Error('We were unable to retrieve the item');
}
});
$('#ResGrid').jqGrid({
defaults: {
emptyrecords: "No items assigned",
loadtext: "Loading..."
},
data: RGrid,
autowidth: true,
datatype: "local",
colModel: [
{ label: 'a', name: 'a', align: 'left', editable: false },
{
label: 'b', name: 'b', align: 'center', editable: true, edittype: 'checkbox',
editoptions: { value: "True:False" },
formatter: "checkbox", formatoptions: { disabled: false }
},
{
label: 'c', name: 'c', align: 'center', editable: true, edittype: 'checkbox',
editoptions: { value: "True:False" },
formatter: "checkbox", formatoptions: { disabled: false }
},
{
label: 'd', name: 'd', align: 'center', editable: true, edittype: 'checkbox',
editoptions: { value: "True:False" },
formatter: "checkbox", formatoptions: { disabled: false }
},
{ name: 'e', hidden: true },
{ name: 'f', hidden: true }
],
rowNum: 1000,
height: 'auto',
viewrecords: true,
caption: "Desc",
grouping: false,
loadonce: true
});
I have tried not passing values for the checkbox columns and several overloads of the addRowData method, none have had an effect. Curiously, the objects passed to the RGrid array appear to have all the property-value pairs I expect, so I suspect the issue is either with the colModel declaration or the way I am using addRowData method.
EDIT: The json I receive from the server:
{"Id":4,"JobNumber":"PrNum75","OrderNumber":null,"QuoteNumber":"1401291641","QuoteId":33,"Requests":[{"Id":10,"PlannedDays":[{"Id":20,"Hours":4.0,"Date":"2014-02-20T00:00:00"}],"PlannedSkillDef":{"Id":1,"Description":"IPE Inspector","DefaultRate":200.0},"QuoteSection":{"Id":54,"Description":"Ves","NumberOf":5,"TotalServices":1000.0,"TotalConsumables":100.0,"TotalTravel":5.0,"TotalAmountPerVessel":1105.0,"TravelExpenses":[{"Id":26,"AgreedRate":3.0,"Quantity":1,"TravelDef":{"Id":1,"Description":"Resource & NDT Travel ","UnitDescription":"Km","DefaultRatePerUnit":3.0}},{"Id":27,"AgreedRate":2.0,"Quantity":1,"TravelDef":{"Id":2,"Description":"Mechanical Service Travel","UnitDescription":"Km","DefaultRatePerUnit":2.0}}],"Consumables":[{"Id":16,"Quantity":1,"AgreedPrice":100.0,"ConsumableDef":{"Id":3,"Description":"Cans of MT / PT consumables","UnitPrice":100.0}}],"Services":[{"Id":17,"ServiceDef":{"Id":1,"Description":"Non Destructive Testing - Inspections","DefaultSkill":{"Id":2,"Description":"CPV","DefaultRate":250.0},"TasksRequired":[{"Id":1,"Description":"Thickness Testing"},{"Id":2,"Description":"Surface Crack Testing"},{"Id":3,"Description":"Reporting"},{"Id":4,"Description":"NDT Travel"}],"TravelDefs":[{"Id":1,"Description":"Resource & NDT Travel ","UnitDescription":"Km","DefaultRatePerUnit":3.0},{"Id":2,"Description":"Mechanical Service Travel","UnitDescription":"Km","DefaultRatePerUnit":2.0}],"ConsumableDefs":[{"Id":3,"Description":"Cans of MT / PT consumables","UnitPrice":100.0}]},"DefaultSkill":{"Id":70,"Rate":0.0,"SkillDef":{"Id":2,"Description":"CPV","DefaultRate":250.0}},"AgreedSkill":{"Id":69,"Rate":250.0,"SkillDef":{"Id":1,"Description":"IPE Inspector","DefaultRate":200.0}},"ServiceTasks":[{"Id":92,"TaskHours":1,"NumberOfShifts":1,"NumberOfStaff":1,"ServiceTaskDef":{"Id":1,"Description":"Thickness Testing"}},{"Id":93,"TaskHours":1,"NumberOfShifts":1,"NumberOfStaff":1,"ServiceTaskDef":{"Id":2,"Description":"Surface Crack Testing"}},{"Id":94,"TaskHours":1,"NumberOfShifts":1,"NumberOfStaff":1,"ServiceTaskDef":{"Id":3,"Description":"Reporting"}},{"Id":95,"TaskHours":1,"NumberOfShifts":1,"NumberOfStaff":1,"ServiceTaskDef":{"Id":4,"Description":"NDT Travel"}}]}]},"Resource":{"Id":1,"ADUserName":"###","Name":"Matthew Smith","SkillDefs":[]},"ServiceDef":{"Id":1,"Description":"Non Destructive Testing - Inspections","DefaultSkill":{"Id":2,"Description":"CPV","DefaultRate":250.0},"TasksRequired":[{"Id":1,"Description":"Thickness Testing"},{"Id":2,"Description":"Surface Crack Testing"},{"Id":3,"Description":"Reporting"},{"Id":4,"Description":"NDT Travel"}],"TravelDefs":[{"Id":1,"Description":"Resource & NDT Travel ","UnitDescription":"Km","DefaultRatePerUnit":3.0},{"Id":2,"Description":"Mechanical Service Travel","UnitDescription":"Km","DefaultRatePerUnit":2.0}],"ConsumableDefs":[{"Id":3,"Description":"Cans of MT / PT consumables","UnitPrice":100.0}]}}],"Consumables":[],"TravelAllocations":[]}
The part of interest to me is WorkRequests, where I need the Name and the Id of the Resource.
you can try doing this in complete: function(){// here your jqgrid}:
"loadonce: true" no need to use this as your datatype is local
var RGrid = [];
$.ajax({
url: restApi + EndPoint + '/' + Number,
type: 'GET',
success: function (response) {
Object2 = response;
var rData = $('#ResGrid').jqGrid().getRowData();
for (var i = 0; i < Object2.Requests.length; i++) {
var existingRows = rData.filter(function (a) {
return a.rId == Object2.Requests[i].Resource.Id;
});
if (existingRows.length == 0) {
var newObj = {
a: jobObject2.Requests[i].Resource.Name,
b: jobObject2.Requests[i].Resource.Id,
c: jobObject2.Requests[i].Id,
d: false,
e: false,
f: false
};
RGrid.push(newObj);
}
}
},
error: function (textStatus) {
Error('We were unable to retrieve the item');
},
complete: function(){
$('#ResGrid').jqGrid({
defaults: {
emptyrecords: "No items assigned",
loadtext: "Loading..."
},
data: RGrid,
autowidth: true,
.........
}
});
It's better if you would use datatype: "json". In the case jqGrid will make the request to the server. You need just use url option like url: restApi + EndPoint + '/' + Number and jsonReader like jsonReader: {root: "Requests", repeatitems: false}. It will inform jqGrid where to find the data in the response. Additionally you would need to use jsonmap option to bind columns with the names 'a', 'b', 'c', ... to properties Resource.Name and other in the server response.
The mapping of jobObject2.Requests[i].Resource.Id and jobObject2.Requests[i].Id to 'b' and 'c' columns having formatter: "checkbox" seems me very suspected. It's strange to have ids which possible value could be True or False only. Additional problem is the usage of variable Object2 in the loop, but usage of undefined jobObject2 in the body of the loop. I suppose that minimal fixing of your current code would be: moving of creating of the grid inside of success or complete callback and replacing jobObject2 to Object2. I would see the problem as the next one. Your current question is: how to fill the grid with the data returned from the server.
The code which I suggest should look about the following:
$('#ResGrid').jqGrid({
datatype: "json",
url: restApi + EndPoint + '/' + Number,
gridview: true,
autoencode: true,
loadonce: true,
jsonReader: {
root: "Requests",
repeatitems: false
},
colModel: [
{ name: "a", jsonmap: "Resource.Name" },
{ name: "b", jsonmap: "Resource.Id", align: "center" },
{ name: "c", jsonmap: "Id", align: "center" }
]
...
});
UPDATED: The demo shows that posted above options work with the last version of JSON data which you posted.
I have figured out what the issue was. The code declaring and populating the jqGrid was in a script file, which in the page was referenced above the declaration of the table that was supposed to act as the grid. A basic novice mistake on my part.
Thank you all for trying to help me out, and sorry to take up your time. Guess it's back to C# for me...
Related
{ label: 'Update Time',
name: 'UPD_DT', formatter: 'date', formatoptions: {
srcformat: 'd-M-y H:i:s', newformat: 'd-M-Y h:i:s' }, width: 400 },
I have used this formatting options in my jqgrid in my pc I'm getting the correct format.
But in another server I'm getting the format as NaN-undefined-NaN 12:NaN:NaN
How can I handle it generically for all the servers having different date time format
Below is the code that do auto detection of date formats. There are some assumptions for this purpose.
We use moment.js library
You should define the expected date formats that come form the server.
The biggest problem for auto detection is format like 10/09/2000 or more worse 10/09/09. To overcome this it is needed to define a set of expected formats.
Working demo using Guriddo jqGrid here
See the comments in code.
If something is not clear, just ask.
Enjoy
$(document).ready(function () {
// define your expected formats from the server
var dateFormats = {
"iso_int" : "Y-m-d",
"short_date" : "d/m/Y",
"iso_date_time": "Y-m-dTH:m:s",
"iso_date_time_utc": "Y-m-dTH:m:sZ",
"my_format1" : "Y/m/d"
//define other well known formats if you want
};
// function uses moment.js to find the format
function getFormat(d){
for (var prop in dateFormats) {
if(moment(d, dateFormats[prop],true).isValid()){
return dateFormats[prop];
}
}
return null;
}
// gloabal array to store the columns with date fields
var datearr =[];
// jqgrid configuration
$("#jqGrid").jqGrid({
url: 'data.json',
mtype: "GET",
datatype: "json",
page: 1,
colModel: [
{ label: 'Order ID', name: 'OrderID', key: true, width: 75 },
{
label: 'Order Date',
name: 'OrderDate',
width: 150,
editable: true,
edittype:"text",
formatter : 'date',
formatoptions : {
newformat: "d/m/Y"
}
},
{
label: 'Customer ID',
name: 'CustomerID',
width: 150,
editable: true,
edittype: "select",
editoptions: {
value: "ALFKI:ALFKI;ANATR:ANATR;ANTON:ANTON;AROUT:AROUT;BERGS:BERGS;BLAUS:BLAUS;BLONP:BLONP;BOLID:BOLID;BONAP:BONAP;BOTTM:BOTTM;BSBEV:BSBEV;CACTU:CACTU;CENTC:CENTC;CHOPS:CHOPS;COMMI:COMMI;CONSH:CONSH;DRACD:DRACD;DUMON:DUMON;EASTC:EASTC;ERNSH:ERNSH;FAMIA:FAMIA;FISSA:FISSA;FOLIG:FOLIG;FOLKO:FOLKO;FRANK:FRANK;FRANR:FRANR;FRANS:FRANS;FURIB:FURIB;GALED:GALED;GODOS:GODOS;GOURL:GOURL;GREAL:GREAL;GROSR:GROSR;HANAR:HANAR;HILAA:HILAA;HUNGC:HUNGC;HUNGO:HUNGO;ISLAT:ISLAT;KOENE:KOENE;LACOR:LACOR;LAMAI:LAMAI;LAUGB:LAUGB;LAZYK:LAZYK;LEHMS:LEHMS;LETSS:LETSS;LILAS:LILAS;LINOD:LINOD;LONEP:LONEP;MAGAA:MAGAA;MAISD:MAISD;MEREP:MEREP;MORGK:MORGK;NORTS:NORTS;OCEAN:OCEAN;OLDWO:OLDWO;OTTIK:OTTIK;PARIS:PARIS;PERIC:PERIC;PICCO:PICCO;PRINI:PRINI;QUEDE:QUEDE;QUEEN:QUEEN;QUICK:QUICK;RANCH:RANCH;RATTC:RATTC;REGGC:REGGC;RICAR:RICAR;RICSU:RICSU;ROMEY:ROMEY;SANTG:SANTG;SAVEA:SAVEA;SEVES:SEVES;SIMOB:SIMOB;SPECD:SPECD;SPLIR:SPLIR;SUPRD:SUPRD;THEBI:THEBI;THECR:THECR;TOMSP:TOMSP;TORTU:TORTU;TRADH:TRADH;TRAIH:TRAIH;VAFFE:VAFFE;VICTE:VICTE;VINET:VINET;WANDK:WANDK;WARTH:WARTH;WELLI:WELLI;WHITC:WHITC;WILMK:WILMK;WOLZA:WOLZA"
}
},
{
label: 'Freigh',
name: 'Freight',
width: 150,
editable: true,
formatter: 'number',
formatoptions :{decimalSeparator: ',', decimalPlaces:2, thousandsSeparator :""}
},
{
label: 'Ship Name',
name: 'ShipName',
width: 150
//editable: true,
}
],
beforeProcessing : function( data, status, xhr) {
// get the columns that are dates
// and store it in global datearr
var i, cm = this.p.colModel;
if(datearr.length === 0 ) {
for( i=0; i<cm.length; i++) {
if(cm[i].formatter && cm[i].formatter === 'date') {
datearr.push({index:i, name: cm[i].name});
}
}
}
//get the first row to test the date formats
var testdata = data.rows[0], formatfound;
for(i=0; i<datearr.length;i++) {
var crd = datearr[i];
formatfound = getFormat( testdata[crd.name] );
// format found
if(formatfound !== null) {
if(cm[crd.index].formatoptions === undefined) {
cm[crd.index].formatoptions = {};
}
// set it in formatoptions
cm[crd.index].formatoptions.srcformat = formatfound;
}
}
return true;
},
loadonce : true,
viewrecords: true,
width: 780,
height: 250,
rowNum: 10,
pager: "#jqGridPager"
});
$("#jqGrid").navGrid("#jqGridPager",
{ edit: false, add: false, del: false, search: true, refresh: true, view: true, align: "left" },
{ closeAfterEdit: true, reloadAfterSubmit : false}
);
$("#chng").on('click', function(){
$("#jqGrid").jqGrid('setGridParam',{url:'data1.json', datatype:'json'}).trigger("reloadGrid");
});
});
For some reason, my grid is blank with no rows (not even an empty row), no navigation icons and no editing icons. I'm using a few add-in features such as an autocomplete field (inside the grid), and a font resizing script so my script is a bit long. The page is receiving the properly formatted response from my functions page and it seems to match my jsonReader settings but it's not populating the grid with it. Here is my JSON formatted response from the page:
{"page":"1",
"total":1,
"records":"4",
"rows":[{"DetailID":"1","Quantity":"2","TaskName":"Differencial With Housing","UnitPrice":"335.00","ExtendedPrice":"670.00"}, {"DetailID":"2","Quantity":"1","TaskName":"Left axel seal","UnitPrice":"15.00","ExtendedPrice":"15.00"},{"DetailID":"3","Quantity":"1","TaskName":"Upper and Lower Bearings","UnitPrice":"55.00","ExtendedPrice":"55.00"}, {"DetailID":"5","Quantity":"1","TaskName":"Fluids","UnitPrice":"45.00","ExtendedPrice":"45.00"}]}
And here is my grid script:
<script>
function autocomplete_element(value, options) {
var $ac = $('<input type="text"/>');
$ac.val(value);
$ac.autocomplete({source: "autocomplete.php?method=fnAutocomplete"});
return $ac;
}
function autocomplete_value(elem, op, value) {
if (op == "set") {
$(elem).val(value);
}
return $(elem).val();
}
$(document).ready(function()
{
$('#filter').jqm();
var selectedRow = 0;
$("#list").jqGrid(
{
url:'managegrid.php',
datatype: 'json',
colNames:['DetailID', 'ProjectID','Qty.','Description','Unit Price','Total Cost'],
colModel :[
{name:'DetailID', index:'DetailID', hidden:true, editable:false},
{name:'ProjectID', index:'ProjectID', width:25, hidden:true, editable:true},
{name:'Quantity', index:'Quantity', editable:true, width:50, align:'right', edittype:'text', editoptions: {defaultValue:'1'}},
{name:'TaskName', index:'TaskName', editable:true, width:450, align:'left', edittype: 'custom', editoptions: {'custom_element' : autocomplete_element, 'custom_value' : autocomplete_value}},
{name:'UnitPrice', index:'UnitPrice', editable:true, width:100, align:'right'},
{name:'ExtendedPrice', index:'ExtendedPrice', editable:false, width:100, align:'right'}
],
onSelectRow: function(id){
if(DetailID && DetailID!==mkinline){
jQuery('#list').saveRow(mkinline);
jQuery('#list').editRow(DetailID,true);
mkinline=DetailID;
}
},
pager: $('#pager'),
rowNum:20,
rowList:[],
pgbuttons: false,
pgtext: null,
sortorder: "asc",
sortname: "DetailID",
viewrecords: true,
imgpath: '/js/jquery/css/start/images',
caption: 'Project Details',
height:'auto',
width:823,
mtype:'GET',
recordtext:'',
pgtext:'',
editurl:"editgrid.php",
toolbar:[true,"bottom"],
loadComplete:function(){
var recorddata = $("#list").getUserData();
$("#t_list").html(recorddata.MSG);
},
jsonReader: {
page: "PAGE",
total: "TOTAL",
records:"RECORDS",
root: "ROWS",
userdata:"USERDATA"
}
}
);
$("#t_list").css("color","blue");
jQuery("#list").jqGrid("inlineNav",'#pager',{edit:true,editicon: "ui-icon-pencil",add:true,addicon: "ui-icon-plus",search:false}, {}, {},
{url:"delgridrow.php",closeAfterDelete:true,reloadAftersubmit:false,afterSubmit:commonSubmit,caption:"Delete",msg:"Delete selected",width:"400"})
.navButtonAdd('#pager',{caption:"",title:"Reload Form",buttonimg:'/js/jquery/css/start/images/refresh.gif',onClickButton:function(id)
{
resetForm();
$("#list").setGridParam(
{
url:"managegrid.php",
page:1
}
).trigger("reloadGrid");
}
});
}
);
function gridSearch()
{
var pid = $("#DetailID").val();
var qty = $("#Quantity").val();
var tn = $("#TaskName").val();
var up = $("#UnitPrice").val();
$("#list").setGridParam(
{
url:"managegrid.php?ProjectID="+pid+"&Quantity="+qty+"&TaskName="+tn+"&UnitPrice="+up,
page:1
}
).trigger("reloadGrid");
$("#filter").jqmHide();
return false
}
function commonSubmit(data,params)
{
var a = eval( "(" + data.responseText + ")" );
$("#t_list").html(a.USERDATA.MSG);
resetForm();
return true;
} function resetForm()
{
window.location.reload(false);
}
</script>
I've been trying to figure this one out all weekend and it's driving me crazy so any help would be appreciated.
You should add the line of code
jQuery("#list").jqGrid("navGrid", '#pager',
{add: false, edit: false, del: false, search: false, refresh: false});
directly before calling of inlineNav.
UPDATED: Your code have many other problems too. For example, you should remove jsonReader option from your code, because it contains wrong values of properties (like root: "ROWS" instead of root: "rows", which is default and can be removed). You can consider to use jsonReader: { id: 'DetailID' } to use the value of DetailID as the rowid and to use DetailID instead of id during editing. I'd recommend you to define all variables before the usage (see mkinline and DetailID for example).
I am using free jqGrid 4.12.1. I want to add, edit and delete rows in the grid and wish to make server side calls for each operation.
I have added editurl and 'actions' formatter as below,
{
name: "actions",
width: 100,
formatter: "actions",
formatoptions: {
keys: true,
editOptions: {},
addOptions: {},
delOptions: {}
}
}
I am adding 'inlineNav' as below,
$("#itemList").jqGrid('inlineNav',"#itemListPager",
{
edit: true,
add: true,
del: true,
search: true,
searchtext: "Search",
addtext: "Add",
edittext: "Edit",
deltext: "Delete"
},
{
closeOnEscape: true, //Closes the popup on pressing escape key
reloadAfterSubmit: true,
drag: true,
url: "${pageContext.request.contextPath}/billing/saveItem",
errorfunc: function (rowId, resp) {
alert(resp);
},
afterSubmit: function (response, postdata) {
if (response.responseText == "") {
$(this).jqGrid('setGridParam', { datatype: 'json' }).trigger('reloadGrid'); //Reloads the grid after edit
return [true, '']
}
else {
$(this).jqGrid('setGridParam', { datatype: 'json' }).trigger('reloadGrid'); //Reloads the grid after edit
return [false, response.responseText]//Captures and displays the response text on th Edit window
}
},
editData: {
EmpId: function () {
var sel_id = $('#itemList').jqGrid('getGridParam', 'selrow');
var value = $('#itemList').jqGrid('getCell', sel_id, '_id');
return value;
}
}
},
{
closeAfterAdd: true, //Closes the add window after add
url: "${pageContext.request.contextPath}/billing/saveItem",
afterSubmit: function (response, postdata) {
if (response.responseText == "") {
$(this).jqGrid('setGridParam', { datatype: 'json' }).trigger('reloadGrid')//Reloads the grid after Add
return [true, '']
}
else {
$(this).jqGrid('setGridParam', { datatype: 'json' }).trigger('reloadGrid')//Reloads the grid after Add
return [false, response.responseText]
}
}
},
{ //DELETE
closeOnEscape: true,
closeAfterDelete: true,
reloadAfterSubmit: true,
url: "${pageContext.request.contextPath}/billing/saveItem",
drag: true,
afterSubmit: function (response, postdata) {
if (response.responseText == "") {
$("#itemList").trigger("reloadGrid", [{ current: true}]);
return [false, response.responseText]
}
else {
$(this).jqGrid('setGridParam', { datatype: 'json' }).trigger('reloadGrid');
return [true, response.responseText]
}
},
delData: {
EmpId: function () {
var sel_id = $('#itemList').jqGrid('getGridParam', 'selrow');
var value = $('#itemList').jqGrid('getCell', sel_id, '_id');
return value;
}
}
},
{//SEARCH
closeOnEscape: true
}
);
The 'inlineNav' added above has no effect because no server side call is made on adding a new row or deleting existing row. The server side call is made only in case of edit, and that call too does not happen through 'inlineNav' code above. Because even if i remove 'inlineNav' code the server side call is still made to the 'editurl'.
So how can i make server side calls on adding/editing/deleting rows and also pass parameters to these calls. I will really appreciate if someone can point me to a working example somewhere. Thanks
UPDATE:-
I have removed 'actions' formatter and modified code to look as below,
<script type="text/javascript">
var dataGrid = $('#itemList');
var firstClick = true;
$(document).ready(function () {
$('#action').click(function () {
if (!firstClick) {
$("#itemList").setGridParam({datatype:'json'}).trigger("reloadGrid");
}
firstClick = false;
$("#itemList").jqGrid({
url: "${pageContext.request.contextPath}/billing/medicines",
datatype: "json",
//styleUI : 'Bootstrap',
mtype: "POST",
autowidth: true,
shrinkToFit: true,
sortname: "Id",
sortorder: "asc",
loadBeforeSend: function(jqXHR) {
jqXHR.setRequestHeader("X-CSRF-TOKEN", $("input[name='_csrf']").val());
},
postData: {
},
loadError: function (jqXHR, textStatus, errorThrown) {
alert('HTTP status code: ' + jqXHR.status + '\n' +
'textStatus: ' + textStatus + '\n' +
'errorThrown: ' + errorThrown);
alert('HTTP message body (jqXHR.responseText): ' + '\n' + jqXHR.responseText);
},
colNames: ["Id", "Item Type", "Item Code", "Unit", "Stock", "Batch No.", "Expiry Date", "Quantity Per Unit", "Price"],
colModel: [
{ name: "itemId", width: 35, align: "left", sorttype:"int", search: false},
{ name: "itemType", width: 100, align: "left", editable: true},
{ name: "itemCode", width: 120, align: "left", editable: true},
{ name: "unit", width: 70, align: "left", search: false, editable: true},
{ name: "availableQuantity", width: 55, align: "left", search: false, formatter: "number", editable: true},
{ name: "batchNumber", width: 80, align: "left", search: false, editable: true},
{ name: "expiryDate", width: 80, align: "left", search: false, sorttype: "date", editable: true, formatoptions: {srcformat:'d/m/Y', newformat:'d/m/Y'}},
{ name: "quantityPerUnit", width: 80, align: "left", search: false, formatter: "number", editable: true},
{ name: "price", width: 55, align: "left", search: false, formatter: "number", editable: true}
],
pager: "#itemListPager",
rowNum: 50,
rowList: [50, 100, 150, 200],
rownumbers: true,
rownumWidth: 25,
sortname: "id",
sortorder: "desc",
viewrecords: true,
height: '100%',
loadonce: true,
//gridview: true,
autoencode: true,
editurl: "${pageContext.request.contextPath}/billing/saveItem",
caption: "Item List",
ondblClickRow: function(rowId){}
}).navGrid('#itemListPager',{add:false,edit:false,del:true});
$("#itemList").jqGrid('filterToolbar', {autoSearch: true, stringResult: true, searchOnEnter: false, defaultSearch: 'cn'});
$("#itemList").jqGrid('gridResize', { minWidth: 450, minHeight: 150 });
var saveparameters = {
"successfunc" : null,
"url" : "${pageContext.request.contextPath}/billing/saveItem",
"extraparam" : {},
"aftersavefunc" : null,
"errorfunc": null,
"afterrestorefunc" : null,
"restoreAfterError" : true,
"mtype" : "POST"
};
var editparameters = {
"keys" : false,
"oneditfunc" : null,
"successfunc" : null,
"url" : "${pageContext.request.contextPath}/billing/editItem",
"extraparam" : {},
"aftersavefunc" : null,
"errorfunc": null,
"afterrestorefunc" : null,
"restoreAfterError" : true,
"mtype" : "POST"
};
var parameters = {
edit: true,
editicon: "ui-icon-pencil",
add: true,
addicon:"ui-icon-plus",
save: true,
saveicon:"ui-icon-disk",
cancel: true,
cancelicon:"ui-icon-cancel",
addParams : saveparameters,
editParams : editparameters
};
$("#itemList").jqGrid('inlineNav',"#itemListPager", parameters);
});
});
</script>
The sample json dada is as,
[
{"itemDetailId":1,"itemId":1,"itemType":"Medicine","itemCode":"Aler-Dryl","itemDesc":"Aler-Dryl","batchNumber":"batch1","expiryDate":"18/02/2017","unit":"tablet","subUnit":"tablet","availableQuantity":120.0,"quantityPerUnit":60.0,"price":122.0},
{"itemDetailId":2,"itemId":2,"itemType":"Medicine","itemCode":"Benadryl","itemDesc":"Benadryl","batchNumber":"batch1","expiryDate":"18/02/2017","unit":"ml","subUnit":"ml","availableQuantity":60.0,"quantityPerUnit":120.0,"price":90.0}
]
Now the url specified in editparameters and saveparameters is getting invoked on editing and adding a row respectively.
Please suggest if above approach is a good one. Also how can we set a request header before edit or save data is posted to server. And i can not find anything like deleteparameters similar to editparameters and saveparameters so that i can use delete specific parameters.
UPDATE 2:-
I could successfully set a request header before server side code is invoked on add/edit row using following code,
$.ajaxSetup({
beforeSend: function (jqXHR, settings) {
jqXHR.setRequestHeader("X-CSRF-TOKEN", $("input[name='_csrf']").val());
}});
UPDATE 3:-
Cleaned up code as per Oleg's suggestions as below. But in the strict mode i am getting JS error now - "Uncaught ReferenceError: saveparameters is not defined"
<script type="text/javascript">
$(document).ready(function () {
"use strict";
var dataGrid = $('#itemList');
var firstClick = true;
$('#action').click(function () {
if (!firstClick) {
$("#itemList").setGridParam({datatype:'json'}).trigger("reloadGrid");
}
firstClick = false;
$("#itemList").jqGrid({
url: "${pageContext.request.contextPath}/billing/medicines",
datatype: "json",
mtype: "POST",
autowidth: true,
loadBeforeSend: function(jqXHR) {
jqXHR.setRequestHeader("X-CSRF-TOKEN", $("input[name='_csrf']").val());
},
colNames: ["Id", "Item Type", "Item Code", "Unit", "Stock", "Batch No.", "Expiry Date", "Quantity Per Unit", "Price"],
colModel: [
{ name: "itemId", width: 35, align: "left", sorttype:"int", search: false, editable: false, key: true},
{ name: "itemType", width: 100, align: "left"},
{ name: "itemCode", width: 120, align: "left"},
{ name: "unit", width: 70, align: "left", search: false},
{ name: "availableQuantity", width: 55, align: "left", search: false, formatter: "number",},
{ name: "batchNumber", width: 80, align: "left", search: false},
{ name: "expiryDate", width: 80, align: "left", search: false, sorttype: "date", formatoptions: {srcformat:'d/m/Y', newformat:'d/m/Y'}},
{ name: "quantityPerUnit", width: 80, align: "left", search: false, formatter: "number"},
{ name: "price", width: 55, align: "left", search: false, formatter: "number"}
],
cmTemplate: {editable: true},
pager: true,
rowNum: 50,
rowList: [50, 100, 150, 200],
rownumbers: true,
rownumWidth: 25,
sortname: "itemType",
sortorder: "asc",
forceClientSorting: true,
viewrecords: true,
height: '100%',
loadonce: true,
//gridview: true,
autoencode: true,
editurl: "${pageContext.request.contextPath}/billing/saveItem",
caption: "Item List"
//ajaxRowOptions: { beforeSend: myTokenSetting }, loadBeforeSend: myTokenSetting where var myTokenSetting = function(jqXHR) { jqXHR.setRequestHeader("X-CSRF-TOKEN", $("input[name='_csrf']").val()); }
}).navGrid({add:false,edit:false,del:true});
$("#itemList").jqGrid('filterToolbar', {autoSearch: true, stringResult: true, searchOnEnter: false, defaultSearch: 'cn'});
$("#itemList").jqGrid('gridResize', { minWidth: 450, minHeight: 150 });
var saveparameters = {
"successfunc" : null,
"url" : "${pageContext.request.contextPath}/billing/saveItem",
"extraparam" : {},
"aftersavefunc" : null,
"errorfunc": null,
"afterrestorefunc" : null,
"restoreAfterError" : true,
"mtype" : "POST"
};
var editparameters = {
"keys" : false,
"oneditfunc" : null,
"successfunc" : null,
"url" : "${pageContext.request.contextPath}/billing/editItem",
"extraparam" : {},
"aftersavefunc" : null,
"errorfunc": null,
"afterrestorefunc" : null,
"restoreAfterError" : true,
"mtype" : "POST"
};
var parameters = {
edit: true,
editicon: "ui-icon-pencil",
add: true,
addicon:"ui-icon-plus",
save: true,
saveicon:"ui-icon-disk",
cancel: true,
cancelicon:"ui-icon-cancel",
addParams : saveparameters,
editParams : editparameters
};
$("#itemList").jqGrid('inlineNav',parameters);
$.ajaxSetup({
beforeSend: function (jqXHR, settings) {
alert('Before Row Send');
jqXHR.setRequestHeader("X-CSRF-TOKEN", $("input[name='_csrf']").val());
}});
});
});
</script>
You should examine the options of inlineNav to find out that you use absolutely wrong options:
jQuery("#grid_id").jqGrid('inlineNav', pagerid, parameters);
where parameters have the form
{
edit: true,
editicon: "ui-icon-pencil",
add: true,
addicon: "ui-icon-plus",
save: true,
saveicon: "ui-icon-disk",
cancel: true,
cancelicon: "ui-icon-cancel",
addParams: {useFormatter : false},
editParams: {}
}
You use the options of another method navGrid
jQuery("#grid_id").jqGrid('navGrid', '#gridpager', {parameters},
prmEdit, prmAdd, prmDel, prmSearch, prmView);
which allows to use form editing.
You wrote that you want to use both formater: "actions" andinlineNav. Thus you would have to provide some options of inline editing twice. I would recommend you to read [the wiki article](https://github.com/free-jqgrid/jqGrid/wiki/New-style-of-usage-options-of-internal-methods). It describes the problems with the usage of form editing usingformatter: "actions"andnavGridtogether. The usage of inline editing have very close problems. You will have to provideaddParamsandeditParamsproperties ofinlineNavand the corresponding options offormatter: "actions"` (see here). To make the code more readable and simple free jqGrid provides another form of editing options.
You can specify all inline editing options inside of inlineEditing option of jqGrid, additional specific options of inlineNav method (if required) in navOptions or in inlineNavOptions, the options of Delete operation in formDeleting and so on. Moreover reloadGrid have the option fromServer: true to restore the original value of datatype ("json", "jsonp", "xml", ...) which you used. You can use reloadGridOptions: { fromServer: true } option of form editing or formDeleting to force reloading from the server.
Moreover your existing code contains many very suspected parts with _id and EmpId. I would strictly recommend you to include the example of format of input JSON data which you use to fill the grid. If you want to use EmpId as the name of rowid why you use _id instead? The code fragment like
EmpId: function () {
var sel_id = $('#itemList').jqGrid('getGridParam', 'selrow');
var value = $('#itemList').jqGrid('getCell', sel_id, '_id');
return value;
}
shows that the current rowid seems be wrong and _id column contains correct information which you need as rowid under the name EmpId.
You can for example use prmNames: { id: "EmpId"} and to add key: true to the column _id. The property key: true in the column _id will inform jqGrid to use the value from the column _id as the rowid and prmNames: { id: "EmpId"} will rename default id property used in Edit and Delete to EmpId. Thus jqGrid will automatically send EmpId parameter with the value from _id column during Delete and Edit operations to the server.
Probably you can remove unneeded column _id from the grid too (at least if you hold the column hidden), but I need to see input data of jqGrid to say you exact options of jqGrid which you can use.
I'm sure that you can essentially reduce your existing code and make it more readable using free jqGrid options, but you have to review your existing code carefully. I suggest you to start with the usage of correct rowid and elimination of all hidden columns which you use. Free jqGrid provides additionalProperties feature which structure is very close to the structure of colModel, but the corresponding properties of input data will be saved in the local data only and not placed in DOM of the table. I can explain all more clear if you would post your existing colModel, jsonReader and example of JSON response returned from the server (1-2 rows of data with dummy data would be enough).
The search button works on the first click, but once it is closed either by clicking the X (close button) or by running a search (setting to close after search) it does not open, there are also no errors in the console so I am unable to determine what is wrong and how to fix it.
var previouslySelectedRow = null;
var rowIsSelected = null;
var previousRowIsSelected = null;
var currentRowId;
var currentCount;
var cancelEditing = function(theGrid) {
var lrid;
if (typeof previouslySelectedRow !== "undefined") {
// 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
theGrid.jqGrid('restoreRow', previouslySelectedRow);
// now we need to restore the icons in the formatter:"actions"
lrid = $.jgrid.jqID(previouslySelectedRow);
$("tr#" + lrid + " div.ui-inline-edit").show();
$("tr#" + lrid + " div.ui-inline-save, " + "tr#" + lrid + " div.ui-inline-cancel").hide();
}
};
var parsedResult = JSON.parse(DecodeAscii(result));
ShowDebugNotification("DEBUG INFO(" + ajaxCall + "): <br />" + result, false);
$("#productsTable").jqGrid({
data: parsedResult,
datatype: "local",
loadonce: true,
height: 'auto',
marginLeft: 'auto',
colNames: [
'Product Id', 'Add', 'Product Name', 'Product Code', 'Customer Price'
],
colModel: [
{ name: 'Id', width: 0, hidden:true },
{ name: "actions", template: "actions", width: 50, formatoptions:{
delbutton: false,
editbutton: false
} },
{ name: 'Name', index: 'Name', width: 550, search: true, searchoptions:{sopt:['eq','bw','bn','cn','nc','ew','en']} },
{ name: 'ProductCode', index: 'ProductCode', width: 150, search: true, searchoptions:{sopt:['eq','bw','bn','cn','nc','ew','en']} },
{ name: 'Price', index: 'Price', width: 100, search: false, formatter: 'currency', formatoptions:{decimalSeparator:".", thousandsSeparator: ",", decimalPlaces: 2, prefix: "$"}}
],
rowNum: 15,
rowList: [5, 10, 15, 20],
pager: true,
gridView: true,
viewrecords: true,
iconSet: "jQueryUI",
sortname: 'Name',
sortorder: 'asc',
inlineEditing: { keys: false },
actionsNavOptions: {
addToCarticon: "ui-icon-cart",
addToCarttitle: "Add item to the cart",
custom: [
{ action: "addToCart", position: "first", onClick: function (options) {
var rowData = $('#productsTable').getRowData(options.rowid);
var cartButton = $(".ui-icon", "#jAddToCartButton_"+options.rowid);
if(cartButton.hasClass("ui-icon-cancel")){
cart.shift(rowData);
cartButton.removeClass("ui-icon-cancel");
cartButton.addClass("ui-icon-cart");
}
else if(cartButton.hasClass("ui-icon-cart")){
cart.push(rowData);
cartButton.removeClass("ui-icon-cart");
cartButton.addClass("ui-icon-cancel");
}
}
}]
},
loadComplete: function() {
$("#add-product-dialog-loading-message").hide();
$(".spinner").hide();
$("#add-product-dialog-form").dialog("open");
//for each object in cart
//if prodcut ID matches product Id in product
//grid then set button to a cancel icon
if(cart.length !== 0){
var cartIds = [];
var jsonCart = JSON.stringify(cart);
var parsedJsonCart = JSON.parse(jsonCart);
var productsInCart = $.grep(parsedJsonCart, function(el, i){
cartIds.push(el.Id);
});
var currentRows = $('#productsTable').getRowData();
var shownProductsThatAreInCart = $.grep(currentRows, function (el, i) {
return $.inArray(el.Id, cartIds) !== -1;
});
if(shownProductsThatAreInCart.length > 0){
var rowIds = $(this).jqGrid('getDataIDs');
$.each(rowIds, function(k, v) {
rowData = $('#productsTable').getRowData(v);
if($.inArray(rowData['Id'], cartIds) !== -1){
alert("Matched Product:\nRowData['id'] = " + rowData['Id'] + "\nto\nProduct in cart: " + cartIds.Id);
$(".ui-icon", "#jAddToCartButton_"+v).removeClass("ui-icon-cart");
$(".ui-icon", "#jAddToCartButton_"+v).addClass("ui-icon-cancel");
}
});
}
}
},
gridComplete: function() {
}
});
$("#productsTable").jqGrid("navGrid", {edit:false,add:false,del:false},
{},// use default settings for edit
{},// use default settings for add
{},// delete instead that del:false we need this
{multipleSearch:false,overlay:false,ignoreCase:true,closeAfterSearch:true,closeOnEscape:true,showQuery:true});
I don't think its a bug as I have seen many demos demonstrating how it is supposed to work, I am guessing I have a mis-configuration, please have a look over my code and help determine the issue.
One thing to keep in mind is I am getting the data to load the grid via an ajax call that returns json, all manipulation is done on the client, there is no posting data back to server at all.
Thank you!
The main problem is the combination of Searching options which you use:
{
multipleSearch: false, // it's default and can be removed
overlay: false, // !!! the option make the problem
ignoreCase: true, // it's not exist at all
closeAfterSearch: true,
closeOnEscape: true,
showQuery: true
}
The usage of the option overlay: false is bad because it makes another option toTop: true not working and the Searching dialog will be placed as the children of jQuery UI Dialog. If you remove the option then one can work with the Searching Dialog more easy and the second problem (a bug in calculation of position of jqGrid Searching Dialog) will not exist. Look at the modified demo:
https://jsfiddle.net/OlegKi/su7mf5k9/3/
UPDATED: It seems one have the problem in creating modal jqGrid dialog inside of modal jQuery UI dialog. The problem could be solved by removing modal: true option from the outer jQuery UI dialog. See https://jsfiddle.net/OlegKi/su7mf5k9/3/
In general one could create hybrid solution which changes the type of jQuery UI dialog from modal to non-modal dynamically, but it could be tricky https://jsfiddle.net/OlegKi/su7mf5k9/5/
Actually creating a filter jqGrid toolbar should be straight ahead as in the "new in 3.5, integrated search toolbar" example or documentation.
However, when I run the line myDataTable.jqGrid('filterToolbar', filterOpts); I always get an error "Unable to get value of the property 'colModel': object is null or undefined" in line 3613 of JQuery.jqGrid.src.js, which is: $.each($t.p.colModel,function(i,n) { ..
Just for the record, version of jqGrid is 4.1.2. The grid itself display / works OK.
Here is the code how I init the grid, most likely I do oversee something very simple.
var ft = document.getElementById("myData"); // this is the HTML table element as usual
var colModel = [
{ name: 'i', index: 'i', width: 60, hidden: true, search: false },
{ name: 'c', index: 'c', width: 100, search: true },
{ name: 'p', index: 'p', width: 100, search: true },
{ name: 'displayed', index: 'displayed', align: 'center', width: 100, formatter: booleanToCheckmark, search: false },
];
$(function() {
$(ft).jqGrid({
datatype: 'clientSide',
data: globals.myData, // Array of objects ("the data"), data is correctly displayed
height: 300,
// autowidth: true,
width: 300,
forceFit: true,
colNames: ['I', 'C', 'P', 'dis.'],
colModel: colModel,
rowNum: 10000,
sortname: 'displayed',
sortorder: 'desc',
viewrecords: true,
gridview: true,
caption: 'XYZ'
});
});
// filter bar
// http://www.trirand.com/jqgridwiki/doku.php?id=wiki:toolbar_searching
var filterOpts = { autosearch: true };
// LINE WHERE IT FAILS
$(ft).jqGrid('filterToolbar', filterOpts);
The error that you try to call filterToolbar outside of $(function() {/*it should be called here*/}); block.
Typically one places all the code inside of $(function() {...});. In the way one reduces additionally the number of global variables which will be added as the properties to window. The usage of global variables increase additionally the probability to have conflicts with other standard global variables.