solution for Design this forms in jqgrid - jqgrid

I Have problem in use jqGrid,Before discussing the question of explain tables.
i have 4 tables CostType,CurrencyUnit , Request,RequestCost .
CostType Table structure
CostId CostName
------- ----------
1 permit
2 Warehouse receipt
3 Warehousing
and Request structure
RequestId RequestNo WaybillNo
------------------------------------------
1 100 120Ac30
2 101 400CA852
and CurrencyUnit table stracture:
UnitId UnitName
------------------
1 Dollar
2 Pound
3 Rial
and CostRequest table stracture
requestId CostId Amount CurrencyUnitId Remark
--------------------------------------------------------
1 2 200 3
1 1 400 1
i want in fill page load grid As follows:
Afterwards user can enter request No in top textbox and click button search As follows:
user can change or enter some Cost Amount for this request As follows:
and click in save button to save in database.
Notes: i'm starter in jqGrid i can fill first Grid other two-step i can not implemet.
please help me . thanks all

It's a little difficult to answer on your question without writing the code for you.
The input field for "RequestNo" (having id="requestNo" for example) and the "Search" button could be simple controls in <fieldset> over the grid. click handler of the "Search" button can just call $("#grid").trigger("reloadGrid", [{page:1}]). Inside of grid definition you can use postData like
var $grid = $("#grid"),
editingRowId,
myEditParam = {
keys: true,
oneditfunc: function (id) { editingRowId = id; },
afterrestorefunc: function (id) { editingRowId = undefined; },
aftersavefunc: function (id) { editingRowId = undefined; }
};
$grid.jqGrid({
...
postData: {
// add requestNo parameter to the request
requestNo: function () { return $("#requestNo").val(); }
},
beforeRequest: function () {
// stop request to the server for empty requestNo
return $("#requestNo").val() !== "" ? true : false;
},
onSelectRow: function (id) {
if (id !== editingRowId) {
if (typeof editingRowId !== "undefined") {
// save previously editing row
$(this).jqGrid("saveRow", editingRowId, myEditParam);
}
// start inline editing. The user should save the row by pressing ENTER
$(this).jqGrid("editRow", id, myEditParam);
}
}
...
});
You can add additionally "Save" button which would call $("#grid").jqGrid("saveRow", editingRowId); to save the last editing row if editingRowId is not undefined.
It is important to add editable: true to all columns which you want to see in editing mode. If you want to have all editing columns in the grid you can use cmTemplate: {editable: true} jqGrid option. It changes the defaults for column definitions defined in colModel.
To have dropdown in the "CurrencyUnit" column you should include additional properties in the column definition:
edittype: "select", editoptions: { value: "Dollar:Dollar; Pound:Pound; Rial:Rial" }

Related

Tablesorter plugin, parser-input-select widget not sorting correctly on jquery ajax load

I am using Motties fork of the tablesorter plugin tablesorter with the input parser widget as well as the grouping widget set in options. I need to perform an ajax call to initilise the table on the second fieldset of a form that passes the values from the first fieldset and displays the corresponding rows from the datbase. This works as expected but the functionality of the table sorter on inputs no longer works after the AJAX load.
I can get static tables to sort correctly, however my table loaded via AJAX does not sort my checkbox column correctly. I can see in the DOM that it the widget functionality isn't being called as the "checked" and "checked-0" classes are not being added to the TR like they are with my static versions.
From my searches I have tried updating the table after the AJAX call but to no affect.
if (tableInitilised == false){
$('#show').load(('ajax/field2.php?country='+$("#p_country").val()+'&category='+$("#p_vid_category").val()+'&system='+$("#p_vid_res").val()), function() {
/* When load is done */
loadTable();
var resort = true,
callback = function(){ console.log('table updated'); };
$('#playlistCreationForm-table').trigger("update", [ resort, callback ]);
});
}
function loadTable()
{
//jQuery("#playlistCreationForm-table").trigger('updateCell');
$('#playlistCreationForm-table').tablesorter({
// hidden filter input/selects will resize the columns, so try to minimize the change
widthFixed : false,
headers: {
0: { sorter: "checkbox" },
1: { sorter: "inputs" }
},
// initialize zebra striping and filter widgets
widgets: [ "group", "filter", "zebra","stickyHeaders" ],
ignoreCase: false,
widgetOptions : {
// filter_anyMatch options was removed in v2.15; it has been replaced by the filter_external option
// If there are child rows in the table (rows with class name from "cssChildRow" option)
// and this option is true and a match is found anywhere in the child row, then it will make that row
// visible; default is false
filter_childRows : false,
// if true, filter child row content by column; filter_childRows must also be true
filter_childByColumn : false,
// if true, include matching child row siblings
filter_childWithSibs : true,
// if true, a filter will be added to the top of each table column;
// disabled by using -> headers: { 1: { filter: false } } OR add class="filter-false"
// if you set this to false, make sure you perform a search using the second method below
filter_columnFilters : true,
// if true, allows using "#:{query}" in AnyMatch searches (column:query; added v2.20.0)
filter_columnAnyMatch: true,
// extra css class name (string or array) added to the filter element (input or select)
filter_cellFilter : '',
// extra css class name(s) applied to the table row containing the filters & the inputs within that row
// this option can either be a string (class applied to all filters) or an array (class applied to indexed filter)
filter_cssFilter : '', // or []
// add a default column filter type "~{query}" to make fuzzy searches default;
// "{q1} AND {q2}" to make all searches use a logical AND.
filter_defaultFilter : {},
// filters to exclude, per column
filter_excludeFilter : {},
// jQuery selector (or object) pointing to an input to be used to match the contents of any column
// please refer to the filter-any-match demo for limitations - new in v2.15
filter_external : '',
// class added to filtered rows (rows that are not showing); needed by pager plugin
filter_filteredRow : 'filtered',
// ARIA-label added to filter input/select; {{label}} is replaced by the column header
// "data-label" attribute, if it exists, or it uses the column header text
filter_filterLabel : 'Filter "{{label}}" column by...',
// add custom filter elements to the filter row
// see the filter formatter demos for more specifics
filter_formatter : null,
// add custom filter functions using this option
// see the filter widget custom demo for more specifics on how to use this option
filter_functions : null,
// hide filter row when table is empty
filter_hideEmpty : false,
// if true, filters are collapsed initially, but can be revealed by hovering over the grey bar immediately
// below the header row. Additionally, tabbing through the document will open the filter row when an input gets focus
// in v2.26.6, this option will also accept a function
filter_hideFilters : false,
// Set this option to false to make the searches case sensitive
filter_ignoreCase : true,
// if true, search column content while the user types (with a delay).
// In v2.27.3, this option can contain an
// object with column indexes or classnames; "fallback" is used
// for undefined columns
filter_liveSearch : true,
// global query settings ('exact' or 'match'); overridden by "filter-match" or "filter-exact" class
filter_matchType : { 'input': 'exact', 'select': 'exact' },
// a header with a select dropdown & this class name will only show available (visible) options within that drop down.
filter_onlyAvail : 'filter-onlyAvail',
// default placeholder text (overridden by any header "data-placeholder" setting)
filter_placeholder : { search : '', select : '' },
// jQuery selector string of an element used to reset the filters
filter_reset : 'button.reset',
// Reset filter input when the user presses escape - normalized across browsers
filter_resetOnEsc : true,
// Use the $.tablesorter.storage utility to save the most recent filters (default setting is false)
filter_saveFilters : true,
// Delay in milliseconds before the filter widget starts searching; This option prevents searching for
// every character while typing and should make searching large tables faster.
filter_searchDelay : 300,
// allow searching through already filtered rows in special circumstances; will speed up searching in large tables if true
filter_searchFiltered: true,
// include a function to return an array of values to be added to the column filter select
filter_selectSource : null,
// if true, server-side filtering should be performed because client-side filtering will be disabled, but
// the ui and events will still be used.
filter_serversideFiltering : false,
// Set this option to true to use the filter to find text from the start of the column
// So typing in "a" will find "albert" but not "frank", both have a's; default is false
filter_startsWith : false,
// Filter using parsed content for ALL columns
// be careful on using this on date columns as the date is parsed and stored as time in seconds
filter_useParsedData : false,
// data attribute in the header cell that contains the default filter value
filter_defaultAttrib : 'data-value',
// filter_selectSource array text left of the separator is added to the option value, right into the option text
filter_selectSourceSeparator : '|',
group_collapsible : true, // make the group header clickable and collapse the rows below it.
group_collapsed : false, // start with all groups collapsed (if true)
group_saveGroups : true, // remember collapsed groups
group_saveReset : '.group_reset', // element to clear saved collapsed groups
group_count : " ({num})", // if not false, the "{num}" string is replaced with the number of rows in the group
// apply the grouping widget only to selected column
group_forceColumn : [], // only the first value is used; set as an array for future expansion
group_enforceSort : true, // only apply group_forceColumn when a sort is applied to the table
// checkbox parser text used for checked/unchecked values
group_checkbox : [ 'selected', 'unselected' ],
// change these default date names based on your language preferences (see Globalize section for details)
group_months : [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ],
group_week : [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
group_time : [ "AM", "PM" ],
// use 12 vs 24 hour time
group_time24Hour : false,
// group header text added for invalid dates
group_dateInvalid : 'Invalid Date',
// this function is used when "group-date" is set to create the date string
// you can just return date, date.toLocaleString(), date.toLocaleDateString() or d.toLocaleTimeString()
// reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Conversion_getter
group_dateString : function(date) {
return date.toLocaleString();
},
group_formatter : function(txt, col, table, c, wo, data) {
// txt = current text; col = current column
// table = current table (DOM); c = table.config; wo = table.config.widgetOptions
// data = group data including both group & row data
if (col === 7 && txt.indexOf("GMT") > 0) {
// remove "GMT-0000 (Xxxx Standard Time)" from the end of the full date
// this code is needed if group_dateString returns date.toString(); (not localeString)
txt = txt.substring(0, txt.indexOf("GMT"));
}
// If there are empty cells, name the group "Empty"
return txt === "" ? "Empty" : txt;
},
group_callback : function($cell, $rows, column, table) {
// callback allowing modification of the group header labels
// $cell = current table cell (containing group header cells ".group-name" & ".group-count"
// $rows = all of the table rows for the current group; table = current table (DOM)
// column = current column being sorted/grouped
if (column === 9) {
$cell.find(".group-name").append(" seconds");
}
if (column === 2) {
$cell.find(".group-name").append("s");
}
},
// event triggered on the table when the grouping widget has finished work
group_complete : "groupingComplete"
}
});
initiliseOrderColumn();
jQuery("#playlistCreationForm-table").trigger('updateCell');
tableInitilised = true;
}
function initiliseOrderColumn()
{
runcheck();
$('input[type=checkbox]').on('input', function()
{
runcheck();
});
function runcheck()
{
$('.order-cell input').each(function(){
//if statement here
// use $(this) to reference the current div in the loop
var numberincount = 0;
// checks if checkbox one column over is checked (i.e. select checkbox)
if($(this).parent().prev().children().children().is(':checked')){
/////////////////////////////////////////////////////////////
// This is all WTF code
numberincount++;
if(numberOfSelectedVideos < numberincount)
{
numberOfSelectedVideos = numberincount;
checkboxvalidation.push($(this).val());
}else
{
}
//////////////////////////////////////////////////////////////
//if checked shows input box for ordering
$(this).addClass('selected').removeClass('not-selected');
}else
{
//else hides input box and clears value or order input
$(this).addClass('not-selected').removeClass('selected').val('');
}
});
}
}
Update:
Ive been trying to troubleshoot this more today to no avail. I've turned on the debugging option the console table printed when detecting parsers for each columns assigns the correct parser for each column. I am recreating a condensed version to post here.
--
If someone could point me in the right direction here I would appreciate it.
Thanks,
Eventually found the solution to my problem in the tablesorter docs loading via ajax
my issue was trying to load the whole table via ajax and then initilising it. changed my ajax request to only return the inner html of tbody. I could then initilise the table on page load on then append the data to the tbody and call a tablesort update successfully
$(document).ready(function(){
$('table').tablesorter({
debug : false,
// hidden filter input/selects will resize the columns, so try to minimize the change
widthFixed : true,
headers: {
0: { sorter: "checkbox" },
1: { sorter: "inputs" }
},
// initialize zebra striping, filter, sticky headers and grouping widgets
widgets: [ "group", "columns", "filter", "zebra","stickyHeaders" ],
// checkbox parser text used for checked/unchecked values
group_checkbox : [ 'selected', 'unselected' ],
group_formatter : function(txt, col, table, c, wo, data) {
// txt = current text; col = current column
// table = current table (DOM); c = table.config; wo = table.config.widgetOptions
// data = group data including both group & row data
if (col === 7 && txt.indexOf("GMT") > 0) {
// remove "GMT-0000 (Xxxx Standard Time)" from the end of the full date
// this code is needed if group_dateString returns date.toString(); (not localeString)
txt = txt.substring(0, txt.indexOf("GMT"));
}
// If there are empty cells, name the group "Empty"
return txt === "" ? "Empty" : txt;
},
group_callback : function($cell, $rows, column, table) {
// callback allowing modification of the group header labels
// $cell = current table cell (containing group header cells ".group-name" & ".group-count"
// $rows = all of the table rows for the current group; table = current table (DOM)
// column = current column being sorted/grouped
if (column === 10) {
$cell.find(".group-name").append(" seconds");
}
if (column === 2) {
$cell.find(".group-name").append("s");
}
},
// event triggered on the table when the grouping widget has finished work
group_complete : "groupingComplete"
}
});
///END tablesorter initilisationg
$( ".nextbtn" ).on('click', function(){
if (fieldsetPos == 1)
{
showPage2();
fieldsetPos = 2;
});
function showPage2()
{
if (tableInitilised == false){
$.tablesorter.clearTableBody( $("table") );
$.get('ajax/field2.php?country='+$("#p_country").val()+'&category='+$("#p_vid_category").val()+'&system='+$("#p_vid_res").val(), function(php) {
// append the "ajax'd" data to the table body
$("table tbody").append(php);
// let the plugin know that we made a update
// the resort flag set to anything BUT false (no quotes) will trigger an automatic
// table resort using the current sort
var resort = true;
$("table").trigger("update", [resort]);
$('table').trigger('applyWidgets');
tableInitilised = true;
recreateTable = false;
//Run Order-cell Hide/Show function
initiliseOrderColumn();
});
//
}
//Show Pages
$( ".field1" ).hide();
$( ".field3" ).hide();
$( ".field2" ).show();
}
});

jqGrid Make a Row readonly

I have a grid setup using form editing. I want the the user to be able to edit only some of the rows. As a start, I figured the easiest way to do this was to have a column (probably hidden) in my server query and XML that denotes the Access or Role the user has. So essentially the grid now has a column "Access Role" with 'Y' or 'N' for each row. (where Y = user can edit, N = View/readonly)
I've tried a couple things to implement this. The best I've come up with is using the rowattr function, but my use is flawed since it hides the row in the grid (I don't want it hidden, just readonly):
function (rd) {
console.log('Row = '+rd.WWBPITM_SURROGATE_ID);
if (rd.ACCROLE === "N") {
console.log('RowAttr '+rd.ACCROLE);
return {"style": "display:none"};
}
This might be a start, but I'm not sure where to go from here and I'm not sure if I'm barking up the wrong tree with using rowattr.
I also tried using setCell in a loadComplete function, like this:
function GridComplete() {
var grid = $('#list1');
var rowids = grid.getDataIDs();
var columnModels = grid.getGridParam().colModel;
console.log('Check ACCROLE');
// check each visible row
for (var i = 0; i < rowids.length; i++) {
var rowid = rowids[i];
var data = grid.getRowData(rowid);
console.log('ACCROLE for '+rowid+' is '+data.ACCROLE);
if (data.ACCROLE == 'N') { // view only
// check each column
//console.log(data);
for (var j = 0; j < columnModels.length; j++) {
var model = columnModels[j];
if (model.editable) {
console.log('Is Editable? '+model.editable);
//grid.setCell(rowid, model.name, '', 'not-editable-cell', {editable: false, edithidden: true});
grid.setCell(rowid, model.name, '', 'not-editable-cell', {editoptions: { readonly: 'readonly', disabled: 'disabled' }});
}
}
}
}
}
But the editoptions don't seem to do anything with this.
Any ideas how to do this?
OK thanks for explaining about Form editing. Here's an example of how to prevent edits on certain records for jqGrid with form editing:
Start with this example of jqGrid form edit: http://www.ok-soft-gmbh.com/jqGrid/MulticolumnEdit.htm
Use the beforeInitData event to check your data before the edit form is displayed. Note that this is bound to the pager object.
Use getGridParam and getCell methods to get the current value you want. In my example I grabbed the client name
Add your own business logic for checking (I don't allow edits on 'test2')
Return false to prevent the edit form from popping up.
This example only handles edit, not insert or delete.
Replace $grid.jqGrid("navGrid", "#pager",...) from the example with this:
$grid.jqGrid("navGrid", "#pager", {view: true},
// Events for edit
{
beforeInitData: function (formid) {
var selectedRow = jQuery("#list").jqGrid('getGridParam','selrow'); //get selected rows
var selectedClient = $("#list").jqGrid('getCell', selectedRow, 'name');
if(selectedClient == 'test2')
{
alert('You are not allowed to edit records for client "' + selectedClient + '"');
return false;
}
}
},
// Events for add
{
beforeShowForm: function (formid) {
}
}
);
You didn't provide much information about how you're updating rows (there are various methods as described in JQGrid web page demos, but I took a guess as to a possible solution. I started with the example on the bottom of this page (trirand's web site wiki for inline_editing) http://www.trirand.com/jqgridwiki/doku.php?id=wiki:inline_editing and made a few changes.
Added a new data column securityGroup, and put in data like 'A', 'B', 'C'
Displayed the new data column in the grid
The example used the onSelectRow event to start editing a row if you clicked on a new row. I updated this callback to check the value of row['securityGroup'], and only start .editRow if it's in securityGroupA
JSFiddle at http://jsfiddle.net/brianwoelfel/52rrunar/
Here's the callback:
onSelectRow: function(id){
var row = $(this).getLocalRow(id);
if(id && id!==lastsel2){
jQuery('#rowed5').restoreRow(lastsel2);
if(row['securityGroup'] == 'A') {
jQuery('#rowed5').editRow(id,true);
}
lastsel2=id;
}
},
If this method won't work for you, please provide more information about how you're currently doing edits with jqGrid. This example obviously is very trivial and doesn't even post to PHP or mysql or anything.
In case it will be helpful for others, here is how I am implementing Read Only rows in Form Editing mode, based on a column which designates what level of access the user has to each row:
In editoptions, use the beforeShowForm event, like so:
beforeShowForm: function (formid) {
console.log('Checking for READONLY '+formid.name);
var selectedRow = jQuery("#list1").jqGrid('getGridParam','selrow'); //get selected rows
var selRole = $("#list1").jqGrid('getCell', selectedRow, 'ACCROLE');
if(selRole == 'N' || selRole == 'S' || selRole == 'R')
{
//$("<div>Sorry, you do not have access to edit this record.</div>").dialog({title: "Access Denied"});
formid.find("input,select,textarea")
.prop("readonly", "readonly")
.addClass("ui-state-disabled")
.closest(".DataTD")
.prev(".CaptionTD")
.prop("disabled", true)
.addClass("ui-state-disabled");
formid.parent().find('#sData').hide();
var title=$(".ui-jqdialog-title","#edithd"+"list1").html();
title+=' - READONLY VIEW';
$(".ui-jqdialog-title","#edithd"+"list1").html(title);
formid.prepend('<span style="color: Red; font-size: 1em; font-weight: bold;">You viewing READONLY data.</span>');
}

How to delete rows with local data in jqgrid

jqGrid parameter loadonce: true is used
Selecting rows and pressing delete button
No url is set
How to delete rows in local data only and suppress this error message ?
Is it possbile to set some dummy url or any other idea to allow row delete?
It would be nice if add and edit forms can be used also with local data.
url: 'GetData',
datatype: "json",
multiselect: true,
multiboxonly: true,
scrollingRows : true,
autoencode: true,
loadonce: true,
prmNames: {id:"_rowid", oper: "_oper" },
rowTotal: 999999999,
rownumbers: true,
rowNum: 999999999,
Update 1
From Oleg answer I understood the following solution:
Disable jqGrid standard delete button
Add new delete button to toolbar.
From this button click event call provided
grid.jqGrid('delGridRow', rowid, myDelOptions);
method.
Multiple rows can selected. How to delete all selected rows, this sample deletes only one ?
Is'nt it better to change jqGrid so that delete, edit, add buttons work without url ? Currently it is required to pass dummy url which returns success always for local data editing.
You can use delRowData method do delete any local row.
You can do use delGridRow from the form editing if you need it. I described the way here and used for formatter:'actions' (see here, here and originally here).
var grid = $("#list"),
myDelOptions = {
// because I use "local" data I don't want to send the changes
// to the server so I use "processing:true" setting and delete
// the row manually in onclickSubmit
onclickSubmit: function(options, rowid) {
var grid_id = $.jgrid.jqID(grid[0].id),
grid_p = grid[0].p,
newPage = grid_p.page;
// reset the value of processing option which could be modified
options.processing = true;
// delete the row
grid.delRowData(rowid);
$.jgrid.hideModal("#delmod"+grid_id,
{gb:"#gbox_"+grid_id,
jqm:options.jqModal,onClose:options.onClose});
if (grid_p.lastpage > 1) {// on the multipage grid reload the grid
if (grid_p.reccount === 0 && newPage === grid_p.lastpage) {
// if after deliting there are no rows on the current page
// which is the last page of the grid
newPage--; // go to the previous page
}
// reload grid to make the row from the next page visable.
grid.trigger("reloadGrid", [{page:newPage}]);
}
return true;
},
processing:true
};
and then use
grid.jqGrid('delGridRow', rowid, myDelOptions);
UPDATED: In case of multiselect: true the myDelOptions can be modified to the following:
var grid = $("#list"),
myDelOptions = {
// because I use "local" data I don't want to send the changes
// to the server so I use "processing:true" setting and delete
// the row manually in onclickSubmit
onclickSubmit: function(options) {
var grid_id = $.jgrid.jqID(grid[0].id),
grid_p = grid[0].p,
newPage = grid_p.page,
rowids = grid_p.multiselect? grid_p.selarrrow: [grid_p.selrow];
// reset the value of processing option which could be modified
options.processing = true;
// delete the row
$.each(rowids,function(){
grid.delRowData(this);
});
$.jgrid.hideModal("#delmod"+grid_id,
{gb:"#gbox_"+grid_id,
jqm:options.jqModal,onClose:options.onClose});
if (grid_p.lastpage > 1) {// on the multipage grid reload the grid
if (grid_p.reccount === 0 && newPage === grid_p.lastpage) {
// if after deliting there are no rows on the current page
// which is the last page of the grid
newPage--; // go to the previous page
}
// reload grid to make the row from the next page visable.
grid.trigger("reloadGrid", [{page:newPage}]);
}
return true;
},
processing:true
};
UPDATED 2: To have keyboard support on the Delete operation and to set "Delete" button as default you can add in the delSettings additional option
afterShowForm: function($form) {
var form = $form.parent()[0];
// Delete button: "#dData", Cancel button: "#eData"
$("#dData",form).attr("tabindex","1000");
$("#eData",form).attr("tabindex","1001");
setTimeout(function() {
$("#dData",form).focus(); // set the focus on "Delete" button
},50);
}

jqGrid - how to add row to subgrid? or how to get primary key from parent row?

I am using ASP.MVC and jqgrid 3.7.2. The data loads OK into the grid and subgrid. Updating the master part of the table works great. I can update or remove a row from the subgrid since one of the fields in the subgrid is the primary key of the parent row. But when trying to add a row when the row is posted back to the server I am having trouble getting the parent row's Id. All the other subgrid values are posted as expected. I thought about trying to get the "selected" row of the parent, but the parent row is not selected, so I am not sure how to go about getting the parent rows Id (primary key) in master table thus will be a foreign key in the detail table. When there is any data is the subgrid, I can also get the parent's id since all my subgrid's rows have that as a hidden field. I noticed that during the post an Id field is part of the postback, but the value is null. Any ideas? I am using editing from the navigation bar.
i just figured a very lazy way of doing the same:
i used :
editurl:"datasource/notas_edit.php?pid="+row_id,
Then i get the value of it with $_GET in php ... lazy but works!
subGridRowExpanded: function (subgrid_id, row_id) {
var currentRow = $('#UtilitiesGrid').jqGrid('getRowData', row_id);
var utilityPrimaryKey = currentRow.UtilityId;
...
colNames: ['parentid','subid',...], //insert parentid column, hidden
colModel: [{name:"parentid", index:"parentid", hidden:true, editable:true,
editoptions: {
disabled:true, //dissabled in case colModel->hidden=false
value:utilityPrimaryKey , //Value for parentid in the add form
},
{name:"subid",index:"subid",key:true,hidden:true}
...
$("#"+subgrid_table_id).jqGrid('navGrid',"#"+pager_id,{
add:true,
del:true,
refresh:true,
refreshstate:"current",
search:false,
},
{},//edit options
//add options
{recreateForm:true //since clearAfterAdd is trueby default, recreate the form so we re-establish value for parent id
});
I ended up saving the primary key when the row was expanded. Then I used that value in the add options for the navgrid
subGridRowExpanded: function (subgrid_id, row_id) {
var currentRow = $('#UtilitiesGrid').jqGrid('getRowData', row_id);
var utilityPrimaryKey = currentRow.UtilityId`;
...
$("#" + subGridTableId).jqGrid('navGrid', "#" + pagerId, { edit: true, add: true, del: true, search: false, view: false, refresh: true },
...
{ // Add Options
reloadAfterSubmit: true,
afterSubmit: CheckForError,
closeAfterAdd: true,
url: "/Options/AddUtilityPwsId/" + utilityPrimaryKey
},

jqGrid - inline edit and trapping edit rules

In my situation, I need to allow users to edit various cells in the grid and then save the whole grid to the server later. I have pretty much solved this issue with inline editing and saving to ‘clientArray’. However, I am trying to use the editRules and have run into some issues.
If I make a column editable, and use edit rules to require it to be a number
{ name: 'Value', index: 'Value', width: 50, sortable: true,edittype: 'text',
editable: true, editoptions: { maxlength: 10 },
editrules:{number: true},
formatter:currencyFmatter, unformat:unformatCurrency },
and I control editing and saving in the onSelectRow event:
onSelectRow: function(id){
if(id && id!==lastSel){
jQuery("#Groups").saveRow(lastSel,true,'clientArray');
jQuery("#Groups").editRow(id,true);
}
lastSel=id
},
I then use a button click event to save the grid. Everything works great untill I put a non-numeric value into the Value cell then click on the row below it. It throw as warning box up and stop the save, but it does not stop me from changing rows. So I now have two rows open for editing. Is there a way to trap the editrule error so I can handle it before moving to the next row.
I have tried to use the functions with saveRow (succesfunc, aftersavefunc, errorfunc, afterrestorefunc), of which all say fire after data is saved to server, which does not appear to work for ‘clientArray’.
Basically, I need to find a way to validate the data in inline editing when saved to ‘clientArray’ and information, suggestions, and particularly, examples would be greatly appreciated.
Thanks.
After playing for awhile, I decided edit rules dont work so well with inLine Editing. So, as you suggested, I made my own validation routine. The trick was figuring out how to get the value of the edited row.
The one thing I am trying to figure out now is how to get the focus to go back to the Value column. Back to the documentation!
if(id && id!==lastSel){
//dont save if first click
if (lastSel != -1) {
//get val of Value to check
var chkval = jQuery("#"+lastSel+"_Value").val() ;
// verify it is a number
if (isNaN(chkval)) {//If not a number
//Send Validation message here
//Restore saved row
jQuery("#Grid").restoreRow(lastSel);
//Return to failed save row
jQuery("#Grid ").setSelection(lastSel,false);
//reopen for editing
jQuery("#Grid ").editRow(lastSel,true);
//Note - dont reset lastSel as you want to stay here }
else {
// If number is good, proceed to save and edit next
jQuery("#Grid ").jqGrid('saveRow',lastSel, checksave, 'clientArray', {}, null, myerrorfunc);
jQuery("#Grid ").editRow(id,true);
lastSel=id;
};
isDirty = true;
};
else {
//first click - open row for editing
alert("new Edit")
jQuery("#Grid ").editRow(id,true);
lastSel=id;}
}
in order to resolve this, I used the plugin jquery.limitkeypress.min.js.
onSelectRow: function(id){
if(id && id!==lastsel){
jQuery('#treegrid').jqGrid('restoreRow',lastsel);
jQuery('#treegrid').jqGrid('editRow',id, true);
$("input[name=Presupuesto]").limitkeypress({ rexp: /^[+]?\d*\.?\d*$/ });
lastsel=id;
}
}
where, "Presupuesto" is the name of the column where I let input data to the user.
It works very good...
To take care of this you can code up your own validation function, myRowIsValid in the example below. Then, just call this function as part of your onSelectRow event handler:
onSelectRow: function(id){
if(id && id!==lastSel){
if (lastSel != null && !myRowIsValid(lastSel) ) {
// Display validation error somehow
return;
}
jQuery("#Groups").saveRow(lastSel,true,'clientArray');
jQuery("#Groups").editRow(id,true);
}
lastSel=id
},
Basically, if the validation fails, then let the user know and do not edit the next row.
I made an array called edit_list, and in the callback oneditfunc I add the rowid to the list, and on aftersavefunc I remove it from the list.
That way you can examine the edit_list in the callbacks to determine if there is a row being edited.
This solution probably did not exist when the OP first asked, but this is how I solved it using the latest jqGrid (4.4.4).
I take advantage of the fact that the saveRow will return true/false on success.
Hopefully this helps.
function StartEditing($grd, id) {
var editparameters = {
"keys": true,
"url": 'clientArray'
};
$grd.jqGrid('editRow', id, editparameters);
$grd[0].LastSel = id;
}
onSelectRow: function(id) {
var $grd = $(this);
if (id && !isNaN($grd[0].LastSel) && id !== $grd[0].LastSel) {
if ($grd.jqGrid('saveRow', $grd[0].LastSel, { "url": 'clientArray' }))
StartEditing($grd, id);
else
$grd.jqGrid('setSelection', $grd[0].LastSel);
}
else
StartEditing($grd, id);
}
To trap edit rules on saveRow event,you can use the inbuilt return type of 'saveRow' .Please mark as answer if you are looking for this
yourcode:
onSelectRow: function(id){
if(id && id!==lastSel){
jQuery("#Groups").saveRow(lastSel,true,'clientArray');
jQuery("#Groups").editRow(id,true);
}
lastSel=id
}
modify code:
onSelectRow: function(id){
if(id && id!==lastSel){
var bool = jQuery("#Groups").saveRow(lastSel,true,'clientArray');
//bool true -->success,false -->invalid row /req field validations
if(bool)
{
//Returns true on sucessful save of record i.e to grid (when using client array)
//and set current selected row to edit mode
jQuery("#Groups").editRow(id,true);
}
else
{
//Set last selected row in edit mode and add required values
jQuery("#Groups").editRow(lastSel,true);
}
}
lastSel=id
}

Resources