I am very new to jqGrid. I am trying to load simple jqgrid using asp.net web api.
The api send back the list of emailDto. The emailDto is plain class with 3 public properties
The problem is the jqgrid is not getting populated. Any help is very much appreciated.
function dataBindToGrid() {
var lastsel;
$("#emailgrid").jqGrid({
url: '/api/email/',
datatype: "json",
mytype: 'GET',
ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
colNames: ['Address ID', 'Type', 'Email'],
colModel: [{ name: 'Address_ID', width: 70, primaryKey: true, editable: false, sortable: false, hidden: false, align: 'left' },
{ name: 'Email_Type', width: 70, editable: true, align: 'left', sortable: false },
{ name: 'Email_Address', width: 200, editable: true, align: 'left', sortable: false }
],
onSelectRow: function (id) {
if (id && id !== lastsel) {
var grid = $("#emailgrid");
grid.restoreRow(lastsel);
grid.editRow(id, true);
lastsel = id;
}
},
//This event fires after all the data is loaded into the grid
gridComplete: function () {
//Get ids for all current rows
var dataIds = $('#emailgrid').jqGrid('getDataIDs');
for (var i = 0; i < dataIds.length; i++) {
//Put row in edit state
$("#emailgrid").jqGrid('editRow', dataIds[i], false);
}
},
rowNum: 3,
viewrecords: true,
caption: "Email Addresses"
});
}
When configured for jsondatatype, jqGrid expects data in the following json format:
{
"total": "xxx",
"page": "yyy",
"records": "zzz",
"rows" : [
{"id" :"1", "cell" :["cell11", "cell12", "cell13"]},
{"id" :"2", "cell":["cell21", "cell22", "cell23"]},
...
]
}
data returned must match this otherwise it will not work. This is the default json structure (you can change this if you want). Depending on what browser you are using, you should be able to see the ajax request and response with what data is being sent and returned when the grid is building itself (Firefox use firebug, IE use the developer toolbar)
as per here
Solved!
Just added to jqGrid below and it works.
jsonReader: {
repeatitems: false,
page: function () { return 1; },
root: function (obj) { return obj; },
records: function (obj) { return obj.length; }
},
Related
I am using autocomplete in a textbox on my jqgrid. But i should not allow the user to select the same item twice. Because of pagination he wont see all data all times. Is there a way that on sending new row to server check for duplicate data in the server and send a status back to jqgrid maybe poping up an alert sayign "row already exist on table". What would be the bst approach to do this validation and notify the user? thanks.
$("#assessmentproduct").jqGrid({
url: 'orthofixServices.asmx/GetProductList',
colNames: ['id', 'Product Description', 'Commission Rate'],
colModel: [
{ name: 'id', hidden: true },
{ name: 'description', index: 'desc', width: 320, editable: true },
{ name: 'commissionrate', index: 'com', width: 120, editable: true, unformat: percentUnFormatter, formatter: percentFormatter, editrules: { number: true} }
],
serializeRowData: function(data) {
var params = new Object();
params.id = 0;
params.prdid = $("#prdid").val();
params.description = data.description;
params.commissionrate = data.commissionrate;
var result = JSON.stringify({ 'passformvalue': params, 'oper': data.oper, 'id': data.id });
return result;
},
mtype: "POST",
rowNum: 4,
height: 93,
width: 400,
pager: '#assessmentpager',
editurl: "orthofixServices.asmx/ModifyProductList"
});
$("#assessmentproduct").jqGrid('navGrid', '#assessmentpager', { add: false, edit: false, del: true, refresh: false, search: false }, {}, {}, { serializeDelData: function(postData) {
return JSON.stringify({ 'passformvalue': null, 'oper': postData.oper, 'id': postData.id });
}
});
$("#assessmentproduct").jqGrid('inlineNav', '#assessmentpager', { addParams: { position: "last", addRowParams: {
"errorfunc": duplicateRow, "aftersavefunc": function() { var grid = $("#assessmentproduct"); reloadgrid(grid); }
}
}, editParams: { "aftersavefunc": function() { var grid = $("#assessmentproduct"); reloadgrid(grid); } }
});
You should just hold the simple rule: if an error occur on the server (for example because of validation error) the server response should contains some error HTTP status code. In the case error message will be displayed to the user.
The exact error processing and the displayed error message format depends from the editing mode which you use. In case of inline editing I would recommend you to use errorfunc and restoreAfterError parameters of the editRow method. In case of form editing the errorTextFormat callback can be very helpful.
I have an interesting issue. I have done this on multiple pages with multiple grids. The first grid works fine the second grid in this case fails to load. and give the following error:
this.p is undefined
...sArray(i)){P=true;h="last";U=f}else{i=[i];P=false}this.each(function(){var D=i.l... line 140 jquery.jqGrid.min.js
The user doble clicks on a row and that sets some variables and then calls the function locationGrid().
Like I said this has worked for me multiple times in the past, however on this page it fails. I have double checked and I am getting data back as shown below:
{"d":"{\"total\":1,\"page\":0,\"records\":1,\"rows\":[{\"invPartLocId\":1053,\"inventoryMasterId\":5,\"location\":null,\"itemType\":\"S\",\"currentQanity\":1,\"adjustedQauntity\":0,\"newLocationQty\":0,\"deptCode\":\"1401 \"}]}"}
Any help would be appreciated.
function locationGrid() {
$('#invLocAdjustGrid').jqgrid({
height: 290,
loadui: "block",
datatype: function (rdata) { getLocationData(rdata); },
colNames: ['invPartID', 'locationPartID', 'Loctaion', 'Type', 'Current QTY', 'Adjusted QTY', 'New Location QTY', 'Dept. Code'],
colModel: [
{ name: 'invPartLocId', width: 2, sortable: false, editable: false, hidden: true },
{ name: 'inventoryMasterId', width: 2, sortable: false, editable: false, hidden: true },
{ name: 'location', width: 250, editable: false, sortable: false },
{ name: 'itemType', width: 120, editable: false, sortable: false, align: 'center' },
{ name: 'currentQanity', width: 50, editable: false, sortable: false },
{ name: 'adjustedQauntity', width: 50, editable: false, sortable: false },
{ name: 'newLocationQty ', width: 50, editable: false, sortable: false },
{ name: 'deptCode', width: 50, editable: false, sortable: false }
],
pager: jQuery('#rptCodesPager'),
viewrecords: true,
width: 890,
gridComplete: function () {
$('#load_invLocAdjustGrid').hide();
$(this).prop('p').loadui = 'enable';
$('#lui_invLocAdjustGrid').hide();
},
afterInsertRow: function (rowid, aData) {
},
ondblClickRow: function (rowid) {
var myID = $('#invLocAdjustGrid').getCell(rowid, 'invPartLocId');
Ldclicked(myID);
}
});
}
function getLocationData(rdata) {
var theID = tempID;
tempID = "";
var myDTO = { 'id': theID };
var toPass = JSON.stringify(myDTO);
$.ajax({
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: "json",
url: "INV_Inventory_Adjustment.aspx/getInventoryLocationById",
data: toPass,
success: function (data, textStatus) {
if (textStatus == "success")
ReceivedLocationData(JSON.parse(getMain(data)).rows);
},
error: function (data, textStatus) { alert('An error has occured retrieving data!'); }
});
}
function ReceivedLocationData(data) {
var thegrid = $('#invLocAdjustGrid');
var isGood = data.length;
for (var i = 0; i < isGood; i++) {
thegrid.addRowData(i + 1, data[i]);
}
}
Sorry, but your code is buggy. Moreover I recommend you to rewrite the whole code and I try to explain why.
The first important error is that you use $('#invLocAdjustGrid').jqgrid({...}); in the locationGrid instead of $('#invLocAdjustGrid').jqGrid({...});. JavaScript is case sensitive, so it's very important to use jqGrid instead of jqgrid.
Next problem exist because you use some variables and functions tempID, Ldclicked and getMain which you not defined in the posted code.
After making minimal changes the demo works. I commented only "POST" to use HTTP GET because I get the JSON directly from the file and have no active components on the wed server.
One more problem which you clear have is that your server code serialize the results twice. Typically one have the problem because of wrong usage of ASMX WebMethods. One should not convert the object to JSON manually. Instead of that one need just return the object itself. Because of the problem the d property of the JSON are not the object itself and is a string which should be one more time be parsed:
{
"d": "{\"total\":1,\"page\":0,\"records\":1,\"rows\":[{\"invPartLocId\":1053,\"inventoryMasterId\":5,\"location\":null,\"itemType\":\"S\",\"currentQanity\":1,\"adjustedQauntity\":0,\"newLocationQty\":0,\"deptCode\":\"1401 \"}]}"
}
Even such wrong formatted data can be read by jqGrid without usage datatype as function. Moreover you should always use gridview: true and never use afterInsertRow and almost never use addRowData. The modified code can be about the following:
var tempID = "abc";
$('#invLocAdjustGrid').jqGrid({
url: "INV_Inventory_Adjustment.aspx/getInventoryLocationById",
mtype: "POST",
datatype: "json",
postData: {
id: function () { return tempID; } // ??? I don't know which data should be send
},
ajaxGridOptions: { contentType: "application/json" },
serializeRowData: function (data) {
return JSON.stringify(data);
},
beforeProcessing: function (data) {
$.extend (true, data, $.parseJSON(data.d));
},
jsonReader: {repeatitems: false},
loadonce: true,
colNames: ['invPartID', 'locationPartID', 'Loctaion', 'Type', 'Current QTY', 'Adjusted QTY', 'New Location QTY', 'Dept. Code'],
colModel: [
{ name: 'invPartLocId', width: 2, key: true, hidden: true },
{ name: 'inventoryMasterId', width: 2, hidden: true },
{ name: 'location', width: 250 },
{ name: 'itemType', width: 120, align: 'center' },
{ name: 'currentQanity' },
{ name: 'adjustedQauntity' },
{ name: 'newLocationQty ' },
{ name: 'deptCode' }
],
cmTemplate: {sortable: false, width: 50},
pager: '#rptCodesPager',
viewrecords: true,
gridview: true,
loadui: "block",
height: 290,
width: 890,
ondblClickRow: function (rowid) {
//Ldclicked(rowid);
}
});
The next demo demonstrate that the code work. I included in the demo the option loadonce: true which can be helpful for you too.
I have a weird one. After changing the data store from session to oracle, when i hit Edit on the 'inlineNav' it always goes to the server with the "add" operation. Any ideas why this could happened?
$("#assessmentproduct").jqGrid({
url: 'orthofixServices.asmx/GetProductList',
colNames: ['id', 'Product Description', 'Commission Rate'],
colModel: [
{ name: 'id' },
{ name: 'description', index: 'desc', width: 170, editable: true },
{ name: 'commissionrate', index: 'com', width: 80, editable: true, unformat: percentUnFormatter, formatter: percentFormatter, editrules: { number: true} }
],
serializeRowData: function(data) {
var params = new Object();
params.id = 0;
params.prdid = parseInt($("#prdid").val());
params.description = data.description;
params.commissionrate = data.commissionrate;
return JSON.stringify({ 'passformvalue': params, 'oper': data.oper, 'id': data.id });
},
mtype: "POST",
rowNum: 4,
height: 93,
width: 400,
pager: '#assessmentpager',
editurl: "orthofixServices.asmx/ModifyProductList"
});
$("#assessmentproduct").jqGrid('navGrid', '#assessmentpager', { add: false, edit: false, del: true, refresh: false, search: false }, {}, {}, { serializeDelData: function(postData) {
return JSON.stringify({ 'passformvalue': null, 'oper': postData.oper, 'id': postData.id });
}
});
$("#assessmentproduct").jqGrid('inlineNav', '#assessmentpager', { addParams: { position: "last", addRowParams: {
"aftersavefunc": function() { var grid = $("#assessmentproduct"); reloadgrid(grid); }
}
}, editParams: { "aftersavefunc": function() { var grid = $("#assessmentproduct"); reloadgrid(grid); } }
});
You use JSON.stringify inside of serializeRowData to serialize the posted data to JSON. It's the reason of the encoding which you describe.
UPDATED: OK! Now I see at the end what's the problem. The reason of the misunderstanding was because you used oper="add" in the title instead of oper=add. I understood you that this is your problem (sending of quoted oper="add" instead of oper=add). OK. The problem with sending of oper=add in case of edit operation is known jqGrid bug which is already fixed in the code on the github (see here). You can make the same changes in jquery.jqGrid.src.js and use the fixed code till the new version of jqGrid will released.
Ive got a jqGrid where i have a some columns and 1 of the columns is a dropdownlist(select) populated from database.
What i want is : When im not in editmode column with dropdowns just have to show text which have to be taken from query, and when im in edit mode it should show dropdown list.
exactly like here: http://www.trirand.com/blog/jqgrid/jqgrid.html go into row editing/input tipyes
here is the code for my grid:
<script type="text/javascript">
var lastsel;
$(document).ready(function () {
$.getJSON('#Url.Action("ConstructSelect")', function (data) {
setupGrid(data);
});
});
function setupGrid(data) {
jQuery(document).ready(function () {
jQuery("#list").jqGrid({
url: '#Url.Action("GetStoreList")',
datatype: 'json',
mtype: 'GET',
colNames: ['Butiks kategori', 'Butik Navn', 'By', 'Sælger'],
colModel: [
{ name: 'Id', index: 'Id', width: 50 },
{ name: 'Butiks Kategori', index: 'StoreId', width: 200, edittype: 'text', align: 'center', editable: false },
{ name: 'Buttiks Navn', index: 'StoreName', width: 200, edittype: 'text', align: 'center', editable: false },
{ name: 'Country', index: 'Country', width: 80, sortable: true, editable: true, edittype: "select", editoptions: { value: data }}],
onSelectRow: function (id) {
if (id && id !== lastsel) {
jQuery('#list').jqGrid('restoreRow', lastsel);
jQuery('#list').jqGrid('editRow', id, true);
lastsel = id;
}
},
editurl: '#Url.Action("GridSave")',
rowNum: 50000,
rowList: [5, 10, 20, 50],
pager: '#page',
sortname: 'Id',
sortorder: "desc",
viewrecords: true,
height: "500px",
imgpath: '/scripts/themes/base/images'
});
jQuery("#list").jqGrid('navGrid', "#page", { edit: false, add: false, del: false });
});
}
</script>
P.S. Ill link code as soon as i am back home
UPDATED: Thanks for an answer, im new to jq, so im making alot of mistakes ofc., but now im back to where i was before, the dropdownlist is not populated with data. i cleaned up the code as u said, so it looks like this now:
btw. The ConstructSelect return a list of Strings
jQuery(document).ready(function () {
jQuery("#list").jqGrid({
url: '#Url.Action("GetStoreList")',
ajaxSelectOptions: { type: "POST", dataType: "json" },
datatype: 'json',
mtype: 'GET',
colNames: ['Butiks kategori', 'Butik Navn', 'By', 'Sælger'],
colModel: [
{ name: 'Kategori', index: 'Kategori', width: 50, key: false},
{ name: 'Navn', index: 'Navn', align: 'center', editable: false },
{ name: 'By', index: 'By', align: 'center', editable: false },
{ name: 'Sælger', index: 'Sælger', editable: true, edittype: "select",
editoptions: { dataUrl: '#Url.Action("ConstructSelect")',
buildSelect: function (data) {
var response = jQuery.parseJSON(data.responseText);
var s = '<select>';
if (response && response.length) {
for (var i = 0, l = response.length; i < l; i++) {
var ri = response[i];
s += '<option value="' + ri + '">' + ri + '</option>';
}
}
return s + "</select>";
}
}
}],
onSelectRow: function (id) {
if (id && id !== lastsel) {
jQuery('#list').jqGrid('restoreRow', lastsel);
jQuery('#list').jqGrid('editRow', id, true);
lastsel = id;
}
},
editurl: '#Url.Action("GridSave")',
rowNum: 50000,
rowList: [5, 10, 20, 50],
pager: '#page',
sortname: 'Id',
sortorder: "desc",
viewrecords: true,
height: "900px"
});
jQuery("#list").jqGrid('navGrid', "#page", {edit:false, add:false, del:false});
});
Okay, slight modifications was needed to get it working :
var response = typeof(data) === "string" ? jQuery.parseJSON(data.responseText):data;
aparently u have to tell buildselect that the data u want to modify is String
But i still have the problem that it doesnt show from begining which sellers is already selected!
Okay after restart it mysticly worked... it is solved now
What you need to do is to use
editoptions: { dataUrl: '#Url.Action("ConstructSelect")' }
instead of
editoptions: { value: data }
Depend on the format of the output of the action ConstructSelect you can need to use an additional property buildSelect of the editoptions. jqGrid expected that the server response on the HTTP 'GET' request of dataUrl will be HTML fragment which represent <select>. For example:
<select>
<option value="de">Germany</option>
<option value="us">USA</option>
</select>
If the server return other formatted data, like JSON data
["Germany","USA"]
or
[{"code":"de","display":"Germany"},{"code":"us","display":"USA"}]
you can write JavaScript function which convert the server response to the HTML fragment of the <select> and set the value of the property buildSelect to the function.
In the answer you will find an example of the function.
If your action support only HTTP POST and no GET you will have to use ajaxSelectOptions: { type: "POST" } parameter additionally, to overwrite the type of the corresponding ajax requests. In the same way you can overwrite other ajax parameters. For example you can use
ajaxSelectOptions: { type: "POST", dataType: "json"}
(defaults are type : "GET" and dataType: "html")
Some other small remarks to the code:
you should not place $(document).ready(function () { inside of another $(document).ready(function () {.
You use 'Id' instead of 'id'. So jqGrid will not find the id property. You can a) rename
'Id' to 'id' b) include additional parameter jsonReader: {id: 'Id'} c) include additional property key: true in the definition of the column 'Id'. Any from the ways will solve the described problem.
You can remove default properties like edittype: 'text', sortable: true or editable: false. See jqGrid documentation which describes the default values of all colModel properties.
You should remove imgpath parameter of jqGrid. The parameter is not exist since many many versions of jqGrid (see here).
We're using a jqGrid 3.8.2 with virtual scrolling to scroll a list of records. It works well if the user is scrolling through the list slowly. As soon as the user grabs the scroll bar and quickly scrolls all the way to the bottom the records returned in the grid are completely out of order and sometimes duplicated. The AJAX call we are making to get the records calls a WCF service that returns the records from a database to the AJAX callback in the jqGrid in which the data then gets loaded to the grid. The database expects a page number which in turn indicates which page of records we want.
I am pretty sure the results are coming back in the wrong order due to timing of the AJAX calls. Meaning the calls aren't always first in first out. Newer calls are likely being returned back to the jqGrid before earlier calls.
Any thoughts on how to get this to work correctly? Any steps that I could take to help get us going in the right direction?
If it helps, here is the js configuration:
PersonalListContactGridControl.GetGridConfig = function() {
var jqGridConfig = {
url: Common.AjaxService.serviceUrl + "/GetPersonalListContacts",
datatype: "JSON",
ajaxGridOptions: { contentType: "application/json; charset=utf-8" },
mtype: "POST",
autowidth: true,
height: PersonalListContactGridControl.Constants.Height,
altRows: true,
sortname: "LastName",
viewrecords: true,
emptyrecords: "",
loadtext: '',
multiselect: true,
//sortorder: "desc",
//- virtual scrolling:: 1 ON / 0 OFF
loadonce: false, // SUPPORT FOR REBIND
rowNum: PersonalListContactGridControl.Constants.GridPageSize,
scroll: 1,
gridview: true,
//- column header text
colNames: ['EndPointID',
PersonalListContactGridControl.Constants.FirstNameColumnDisplayText,
PersonalListContactGridControl.Constants.LastNameColumnDisplayText,
PersonalListContactGridControl.Constants.EmailFaxColumnDisplayText,
PersonalListContactGridControl.Constants.TypeColumnDisplayText],
//- column specific definitions
colModel: [
{ name: 'EndPointID', index: 'EndPointID', hidden: true },
{ name: 'FirstName', index: 'FirstName', width: 155, align: 'left', editable: false, title: true,
hidden: false, resizable: true, sortable: true, editoptions: { readonly: true },
formatter: PersonalListContactGridControl.formatLink },
{ name: 'LastName', index: 'LastName', width: 155, align: 'left', editable: false, title: true,
hidden: false, resizable: true, sortable: true, editoptions: { readonly: true },
formatter: PersonalListContactGridControl.formatLink },
{ name: 'EmailAddress', index: 'EmailAddress', width: 240, align: 'left', editable: false, title: true,
hidden: false, resizable: true, sortable: true, editoptions: { readonly: true },
formatter: PersonalListContactGridControl.formatEmailFax },
{ name: 'EndPointType', index: 'EndPointType', width: 60, align: 'left', editable: false, title: true,
hidden: false, resizable: true, sortable: true, editoptions: { readonly: true },
formatter: PersonalListContactGridControl.formatType }
],
//- jqGrid's "reader" ... the structure of the JSON/XML returned (Fiddler) must match this
jsonReader: {
root: "d.Contacts",
total: function(obj) {
return Math.ceil(obj.d.TotalRecords / PersonalListContactGridControl.Constants.GridPageSize);
},
records: function(obj) {
return obj.d.TotalRecords;
},
id: 'EndPointID',
repeatitems: false
},
serializeGridData: function(jqGridParms) {
//alert(jqGridParms.page);
return PersonalListContactGridControl.GetRequest(jqGridParms);
},
loadComplete: function(data) {
if (data.d) {
if (data.d.ResponseProperties.Success === false) {
if (data.d.ResponseProperties.ErrorMessage.indexOf('The List has been deleted') > -1) {
ManagePersonalList.OnPersonalListErrorHandler();
return;
}
}
var grid = PersonalListContactGridControl.Grid();
if (data.d.Contacts == null || data.d.Contacts.length == 0) { // are there any records?
// check if row exists
if (!grid.getInd(-1)) {
if (PersonalListContactGridControl.SearchString == "") {
grid.addRowData(-1, { "FirstName": PersonalListContactGridControl.Constants.NoContactDisplayText });
}
else {
grid.addRowData(-1, { "FirstName": PersonalListContactGridControl.Constants.NoContactForSearchDisplayText });
}
grid.find('#-1 input').hide(); // takeout the selection checkbox
}
PersonalListGridControl.ToggleExportButton(false);
}
else {
if (PersonalListContactGridControl.Constants.dtoToSelectID != null) {
if (PersonalListContactGridControl.SelectContactById(PersonalListContactGridControl.Constants.dtoToSelectID, true))
PersonalListContactGridControl.Constants.dtoToSelectID = null;
}
PersonalListGridControl.ToggleExportButton(true);
}
// cache the return objects
PersonalListContactGridControl.DTOS = PersonalListContactGridControl.DTOS.concat(data.d.Contacts);
PersonalListContactGridControl.InitRows();
}
},
loadError: function(xhr, status, error) {
alert("Type: " + status + "; Response: " + xhr.status + " " + xhr.statusText);
},
onCellSelect: function(rowid, iCol, cellcontent, e) {
if (iCol == 0)
PersonalListContactGridControl.CheckItem();
else
PersonalListContactGridControl.SelectContactById(rowid);
},
onSelectRow: function(id, status) {
if (!status) return;
},
onSelectAll: function() {
var grid = PersonalListContactGridControl.Grid();
var selections = new Array();
selections = grid.getGridParam('selarrrow');
if (selections[0] == -1) {
//if -1, then no rows are available
PersonalListContactGridControl.UpdateHeaderCount(0);
}
else {
PersonalListContactGridControl.UpdateHeaderCount(selections.length);
ManagePersonalList.OnSelectAllChanged(this, { Ids: selections });
}
}
};
return jqGridConfig;
}
Try changing your JSONReader to..
jsonReader: {
root: "d.Contacts",
page: "d.currpage",
total: "d.totalpages",
records: "d.TotalRecords",
id: 'EndPointId',
repeatitems: false
},
the d.totalpages and d.currpage should come back from the AJAX call