Subgrid not getting populated in free jqGrid - javascript

I am trying to add subgrid to every row of main grid. The main grid populates fine but when i click on the expand icon of a row subgrid is not populated. Only subgrid column headers appear.
The json data is a single nested data structure which is fetched only once when grid loads first time. So when i click on the grid expand icon i expect subgrid to be populated from the data that was fetched while displaying the parent grid.
The empty subgrid is displayed when i use - datatype: "local".
If i set datatype: "json" then a server side call is made to fetch data if i click on expand icon.
So how can i display subgrid using the single json data that was already fetched. Thanks
Please find sample code below,
$(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/items",
datatype: "json",
mtype: "POST",
autowidth: true,
loadBeforeSend: function(jqXHR) {
jqXHR.setRequestHeader("X-CSRF-TOKEN", $("input[name='_csrf']").val());
},
colNames: ["Id", "Item Type", "Item Code"],
colModel: [
{ name: "id", width: 35, sorttype:"int", search: false, editable: false, key: true, hidden: true},
{ name: "itemType", width: 100},
{ name: "itemCode", width: 120}
],
maxHeight: 400,
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",
subGrid: true,
subGridRowExpanded: function (subgridId, rowid) {
var subgridTableId = subgridId + "_t";
$("#" + subgridId).html("<table id='" + subgridTableId + "'></table>");
$("#" + subgridTableId).jqGrid({
datatype: "local",
data: $(this).jqGrid("getLocalRow", rowid).itemDetails,
colNames: ["Id", "Unit", "Stock", "Batch No.", "Expiry Date", "Quantity Per Unit", "Price"],
colModel: [
{ name: "id", width: 35, sorttype:"int", search: false, editable: false, key: true, hidden: true},
{ name: "unit", width: 70, search: false},
{ name: "availableQuantity", width: 55, search: false, formatter: "number",},
{ name: "batchNumber", width: 80, search: false},
{ name: "expiryDate", width: 80, search: false, sorttype: "date", formatoptions: {srcformat:'d/m/Y', newformat:'d/m/Y'}},
{ name: "quantityPerUnit", width: 80, search: false, formatter: "number"},
{ name: "price", width: 55, search: false, formatter: "number"}
],
height: "100%",
rowNum: 10,
idPrefix: "s_" + rowid + "_",
cmTemplate: {editable: true},
editurl: "${pageContext.request.contextPath}/billing/saveItem"
});
}
}).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 });
});
The sample json data:-
[{"id":1,"itemCode":"Omez","itemType":"Medicine","itemDesc":"Omez for acidity","itemDetails":[{"id":1,"batchNumber":"batch1","expiryDate":"01/06/2018","unit":"bottle","subUnit":"tablet","availableQuantity":120.0,"quantityPerUnit":60.0,"price":122.0}]}]

First of all it's important to understand that the data, returned from url will be read and saved locally in case of usage loadonce: true option of jqGrid. By default it read only the data for the columns of the grid and the property id (can be configured by id property of prmNames parameter). Free jqGrid allows to read and save any other additional properties. To specify the properties one can use additionalProperties. The simplest for of the usage would be
additionalProperties: ["itemDetails"]
It informs jqGrid to read and save locally itemDetails property of every item. After that $(this).jqGrid("getLocalRow", rowid).itemDetails will work.
Additionally you can remove the column id from colModel. jqGrid set id attribute of the rows based on the value of id property of input data (returned from the server). Thus you don't need to hold the duplicate information in hidden <td> cell of every row. You can remove the id column from both main grid and the subgrid.
If you want to set search: false for all columns of subgrid then you can use cmTemplate: {search: false} option of subgrid and remove search: false from all columns. In the same way you can include in cmTemplate the property width: 80 (cmTemplate: {search: false, width: 80}) to change the default value 150 for the width property to 80. After that you can remove width: 80 from tree columns of subdrid too.
You can remove sortorder: "asc" and height: '100%' properties, because there are default for free jqGrid. You can use
searching: {
stringResult: true,
searchOnEnter: false,
defaultSearch: 'cn'
}
The property autosearch: true (not autoSearch: true) are default. After that you can use filterToolbar without additional parameters.
I would recommend you to use additional option of navGrid: reloadGridOptions: { fromServer: true } which informs to reload the data from the server (by restoring original value of datatype) if the user clicks on Refresh button of navigator bar.

Related

jqgrid : Inline checkbox editing in Client Side

I am using jqgrid. I want to allow people to use a checkbox in inline editing. There will not be any buttons like edit etc, As soon as he clicks the checkbox, it should be considered as committed on client side.
There is a checkbox which I want to always keep in edit mode. After user is done making changes, he will click on a submit button & full grid data will get posted to the server.
I expect that getGridParam method should give me the updated cell values. However it is not doing so.
I feel my problem is the onSelectRow method. somewhere I am missing the implementation to save the current row state. & hence in the getGridParam method. I am getting the original values.
Code :
var lastsel;
jQuery("#AcOpenDataGrid").jqGrid({
url: '/Admin/Role/GetMappedMenus',
viewrecords: true, sortname: 'Code', sortorder: "desc",
colNames: [
"Code",
"MenuName",
"Allow"
],
colModel: [
{ name: 'Code', width: 10, key: true, align: 'center', hidden: true },
{ name: 'MenuName', index: 'MenuName', width: 60, search: true, searchoptions: JQ_sopt_string, align: 'left' },
{ name: 'Allow', index: 'Allow', width: 30, editable: true,edittype:'checkbox',editoptions: { value:"True:False" },formatter:'checkbox', formatoptions: {disabled : false} ,search: true, searchoptions: JQ_sopt_string, align: 'center' },
],
height: '500',
autowidth: true,
rowList: JQ_Paging_Opt,
rowNum: JQ_RowNum_Opt,
pager: pager_selector,
datatype: 'json', mtype: 'GET',
cmTemplate: { title: false },
loadonce:true,
altRows: true,
jsonReader: { root: "rows", page: "page", total: "total", records: "records", repeatitems: false, userdata: "userdata", id: "Code" },
editurl: 'clientArray',
onSelectRow: function (id) {
if (id && id !== lastsel) {
jQuery(grid_selector).jqGrid('restoreRow', lastsel);
//jQuery(grid_selector).jqGrid('saveRow', lastsel);
jQuery(grid_selector).jqGrid('editRow', id, true);
lastsel = id;
}
},
}).navGrid(pager_selector, { view: false, del: false, add: false, edit: false, search: false, refresh: true }
).jqGrid('filterToolbar', { stringResult: true, searchOnEnter: false, defaultSearch: 'cn' });
});
$(".submit").click(function () {
var localGridData = $("#AcOpenDataGrid").jqGrid('getGridParam', 'data');
//To Do : Post Ajax here.
});
I found a solution here. Not exactly what I expected but it does serves my purpose.
Make a column be a checkbox
beforeSelectRow: function (rowid, e) {
var $self = $(this),
iCol = $.jgrid.getCellIndex($(e.target).closest("td")[0]),
cm = $self.jqGrid("getGridParam", "colModel"),
localData = $self.jqGrid("getLocalRow", rowid);
if (cm[iCol].name === "closed") {
localData.closed = $(e.target).is(":checked");
}
return true; // allow selection
},

jqGrid - How can i disable column draggable but can sortable columns

I want to disable reordering by dragging the column but jqGrid works sorting columns.
OR, I want to enable reordering by dragging the column and having column chooser.
This code is occured error by dragging the column.
$(function () {
jQuery("#search_datagrid").jqGrid("GridUnload").jqGrid({
url: '/Search/SearchDataGrid/',
datatype: "json",
contentType: "application/json; charset-utf-8",
mtype: 'POST',
postData: {
search_word: search_word,
baseLang: baseLang,
targetLang: targetLang,
products: products
},
rowNum: 20,
rowList: [10, 20, 30, 50],
colNames: columnNames,
colModel: columnModels,
shrinkToFit: true,
height:'auto',
autowidth: true,
pager: "#search_pager",
viewrecords: true,
caption: "Result",
subGrid: true,
sortable: true,
loadonce: true,
gridview: true,
subGridOptions: {
"plusicon": "ui-icon-triangle-1-e",
"minusicon": "ui-icon-triangle-1-s",
"openicon": "ui-icon-arrowreturn-1-e"
},
})
.jqGrid('navGrid', '#search_pager', { add: false, edit: false, del: false, search: false, refresh: false })
.jqGrid('navButtonAdd', '#search_pager', {
caption: "Select Columns",
title: "Select Columns",
buttonicon: "ui-icon-calculator",
onClickButton: function () {
jQuery("#search_datagrid").jqGrid('columnChooser');
}
})
.jqGrid('setGroupHeaders', {
useColSpanStyle: true,
groupHeaders: [
{ startColumnName: '' + baseLang, numberOfColumns: 2, titleText: 'Language' },
]
})
});
$(window).resize(function () {
$("#search_datagrid").setGridWidth($(this).width() - $(this).width() / 10);
});
The grid option sortable: true, which you use, is responsible for resorting (reordering) of columns with respect of drag and drop of column headers. On the other side sortable: false property of colModel can be used to prevent sorting of data in the column by click on the column header. Reordering of columns with respect of columnChooser is independent from the above options and properties, but one can use hidedlg: true property in colModel to prevent displaying some columns in Column Chooser dialog.
Thus, if I correctly understand your problem, you should just remove sortable: true of the grid and not specify any sortable property inside of colModel (the default value of sortable property is true, which allows sorting of data).

Why does jqGrid refuses to call it's Ajax Call more than once using the OnSelectRow Event

I have a problem with my two jqGrid grids. First I have one grid with some data that works just fine. It has an loadComplete event which sets the first row as selected. This is so that the second jqGrid gets populated based on the selected row (id) on the first jqGrid.
I have an onSelectRow event on the first grid which calls a function which contains the $('#grid).jqGrid() call of the second grid. This second grid has en url which links to a method in a controller which gets some data from a database.
This works all fine for the first selectrow (which happends automatically after the loadComplete).
My problem is that the second jqGrid doesnt repopulate after I select a different row. The programm never gets to the method in the controller (I tested with some logging). I'm really stuck at this since it works for the first load but not the second and so on.
$("#fontsgrid").jqGrid({
url: 'getfonts',
mtype: "post",
datatype: "json",
sortable: true,
colNames: ['Name', 'Family', 'Cost', 'Lic', 'File', 'Added', 'Mod', 'Add', 'Edit'],
colModel: [
{ name: 'name', index: 'name', width: 90, sorttype: "text", sortable: true, align: 'left'},
{ name: 'family', index: 'family', width: 100, sorttype: "text", sortable: true},
{ name: 'cost', index: 'cost', width: 60, sorttype: "currency", sortable: true, formatter: 'currency', formatoptions: {decimalSeparator: ",", thousandsSeparator: ",", decimalPlaces: 2, prefix: "€ "}},
{ name: "licenses", index: "licenses", width: 30, sorttype: "int", sortable: true},
{ name: "filename", index: "filename", width: 90, sorttype: "text", sortable: true},
{ name: "date_upload", index: "date_upload", width: 80, sortable: true, sorttype: "date", formatter: "date", formatoptions: { newformat: 'Y-m-d' }},
{ name: "date_edit", index: "date_edit", width: 80, sortable: true, sorttype: "date", formatter: "date", formatoptions: { newformat: 'Y-m-d' }},
{name: "add_cart", index: 'add_cart', width: 70},
{name: "edit", index: "edit", width: 30}
],
rowNum: 100,
width: 580,
height: 359,
rowList: [100, 250, 500],
sortname: "name",
sortorder: 'asc',
viewrecords: true,
gridview: true,
caption: "Font List",
pager: $('#pager'),
loadComplete: function () {
$('#fontsgrid').jqGrid('setSelection', $("#fontsgrid tr[role]").next().attr("id"));
},
onSelectRow: function (id) {
loadInstallGridFonts(id);
}
}).navGrid('#pager', {edit: false, add: false, del: false});
function loadInstallGridFonts($fontid) {
$('#installGridFonts').jqGrid({
url: 'getinstallations',
mtype: "post",
datatype: "json",
sortable: true,
postData: {'fontid': $fontid},
colNames: ['Installation', 'Bedrijfsnaam', 'Date Installed', 'Edit'],
colModel: [
{ name: 'installation', index: 'installation', width: 90, sorttype: "text", sortable: true, align: 'left'},
{ name: 'bedrijf', index: 'bedrijf', width: 100, sorttype: "text", sortable: true},
{ name: "date_installed", index: "date_installed", width: 80, sortable: true, sorttype: "date", formatter: "date", formatoptions: { newformat: 'Y-m-d' }},
{name: "edit", index: "edit", width: 30}
],
rowNum: 50,
width: 480,
height: 359,
altRows: 'true',
rowList: [50, 75, 100],
sortname: "installation",
sortorder: 'asc',
viewrecords: true,
gridview: true,
caption: "Installation List",
pager: $('#pagerInstall')
}).navGrid('#pagerInstall', {edit: false, add: false, del: false});
}
'getfonts' and 'getinstallations' are both aliases for a controller/method used in routing (codeIgniter).
The problem is that the programm only goes to the method behind the 'getinstallations' once and not after a new rowselect.
I see many problems in your code. First of all it's important to understand that the code like
$('#installGridFonts').jqGrid({
...
});
create the grid. It means that it convert <table> element, which you placed initially on the page, to relatively complex structure of divs and tables (see here for examples). The consequence of it: you can make such call only once. If you try to create the same grid at the second time jqGrid verify that the grid already exist and do nothing. It's exactly what you can see.
One more important thing is the following: jqGrid creates the structure of divs and tables which represent the grid once, but it can fill the body of the grid (the data inside of the grid) multiple times. If you need to fill the grid with the data returned from the server you should just set parameters of the grid (url, datatype, postData and so on) and then make $("#installGridFonts").trigger("reloadGrid"). The reloading means executing new request to the server and loading the data in the the grid.
So the code could be about the following:
// we will use navGrid below more as once without editing buttons
// so we change defaults of navGrid with the folling settings
$.extend($.jgrid.nav, {edit: false, add: false, del: false});
// creates the second grid. because we don't want to make any request
// to the server at the time we will use datatype: "local"
$("#installGridFonts").jqGrid({
datatype: "local",
...
}).jqGrid("navGrid", "#pagerInstall");
// create the first grid
$("#fontsgrid").jqGrid({
...
onSelectRow: function (rowid) {
$("#installGridFonts").jqGrid("setGridParam", {
datatype: "json",
postData: {fontid: rowid}
}).trigger("reloadGrid");
}
}).jqGrid("navGrid", "#pager");
If it's required you can hide the second grid directly after creating and show it inside of onSelectRow callback.

Jqgrid Setting Options From different Javascript files

I want to centralize the options for my jqgrids into one javascript file that all my grids can use. Such as if its sortable, height, width and the methods such as onSelectRow and loadComplete. I then want to load the options which are specific to that grid such as colModel, caption and sort order in a different javascript file for example
GridMain.js
datatype: 'local',
height: 'auto',
width: 'auto',
pager: $('#pager'),
rowNum: 10,
rowList: [5, 10, 20, 50],
sortorder: "asc",
viewrecords: true,
sortable: true,
onSelectRow: function (id) {
//redirect to brand details page
document.location.href = url + id;
}
UserGrid.js
colModel: [
{ name: 'Id', index: 'Id', hidden: true, key: true },
{ name: 'Name', index: 'Name', width: 250, align: 'left' },
{ name: 'Disabled', index: 'Deleted', width: 100, align: 'left' },
{ name: 'Actions', index: 'Actions', width: 150, align: 'center', sortable: false, title: false}],
sortname: 'Name',
caption: "Users"
});
I have tried many different ways and i cant seem to figure it out. I tried using the setGridParam method but height, width, colModel cant be changed after the grid is created.
I am using tableToGrid('.table-to-grid', { options }); to initialize my grid
Any help would be appreciated. Thanks
You can include in the GridMain.js the code like
$.extend($.jgrid.defaults, {
datatype: 'local',
viewrecords: true,
height: 'auto',
...
});
(see here for more information).
You can also confider to defining column templates (see here).
I don't recommend you to use tableToGrid and better create jqGrid directly.

Implementing Delete and Edit operations in jqgrid

i have the following JQgrid implementation
colModel: [
{ name: 'NameEn', index: 'NameEn', width: 100, align: 'left' },
{ name: 'Desc', index: 'Desc', width: 100, align: 'left' },
{ name: 'ID', index: 'ID', width: 100, align: 'left', hidden:true }
],
caption: "Management",
gridview: true,
rownumbers: true,
rownumWidth: 40,
scroll: 0,
rowNum: 100,
sortname: 'ID',
pager: '#pager',
sortorder: "asc",
viewrecords: true,
autowidth: true,
width: '100%',
height: '100%',
jsonReader: { root: "GridData", page: "CurrentPage", total: "TotalPages", records: "TotalRecords", repeatitems: false, id: "00" }
};
SectorGrid.prototype.SetupGrid = function (selector) {
jQuery(selector).html('<table id="grid"></table><div id="pager"></div>');
var grid = jQuery("#grid").jqGrid(this.gridConfiguration);
jQuery("#grid").navGrid('#pager',{edit:false,add:false,del:true,search:false})
};
i want to add a delete functionality, the delete call a webservice with the url http://localhost/services.svc/sector(id) and the service just take the id and it will handle everything by it self also i would like to edit data using differnt url http://localhost/services.svc/sector and this receives json object with the same information above. i really tried to configure it but it wont work can somebody help me in this, it dosent matter if u used the delete option in the jqgrid or custom buttons but i dont want to use the editurl property.
please put a full example how to implement this continue to my code above
UPDATED: Rest Method
[WebInvoke(UriTemplate = "Sector({iD})/", Method = "DELETE", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
[OperationContract]
bool DeleteSector(string iD)
thanks in advance
Try to use navGrid in the form
jQuery("#grid").jqGrid('navGrid', '#pager',
{edit: false, add: false, search: false}, {}, {},
{ // Delete parameters
ajaxDelOptions: { contentType: "application/json" },
mtype: "DELETE",
serializeDelData: function () {
return ""; // don't send and body for the HTTP DELETE
},
onclickSubmit: function (params, postdata) {
params.url = '/Sector(' + encodeURIComponent(postdata) + ')/';
}
});

Categories