Free jqGrid: Field undefined error when extending postdata with local data - javascript
I have been upgrading my projects to jQuery 1.12.0 and the latest version of free jqGrid. I am now seeing an field undefined error here in jquery.jqGrid.src.js:
this.execute = function() {
var match = _query, results = [];
if (match === null) {
return self;
}
$.each(_data, function() {
if (eval(match)) { results.push(this); }
});
_data = results;
return self;
};
The match string looks like:
(String(ErrorCells).toUpperCase() !== String("0").toUpperCase())
I'm filtering out rows with errors (ErrorCells is used as a bit field), but it looks like an explicit this.ErrorCells is necessary. I can't wrap my head around what exactly changed and if there is a resolution without modifying the jqGrid source.
**** UPDATE ****
Below you can see that in the $.each handler, ErrorCells is undefined, but this.ErrorCells is.
This is the code extending the postdata with the filtering criteria:
$.extend(postdata, { // - set filter condition
filters: '',
searchField: 'ErrorCells',
searchOper: 'ne',
searchString: '0'
});
$grid.jqGrid('setGridParam', { search: true, postData: postdata });
$grid.trigger('reloadGrid', [{ page: 1}]);
and this is the grid configuration:
$grid.jqGrid({
url: "Loader.svc/GetData", // - web invoke post
editurl: "clientArray", // - normally the endpoint to post edits, in this case we just edit local data
postData: { "uniqueFolder": uniqueFolder, "xlsName": xlsName, "solIds": GetSolIdString(), "subcompany": _selectedConfiguration.MYSUBCOMPANY, "requireSolId": _selectedConfiguration.MYISBRANCHIDREQ },
datatype: "json",
loadonce: true, // - load data once on server side, then switch to local data handling
mtype: "POST",
ajaxGridOptions: { contentType: "application/json", cache: false },
serializeGridData: function(postData) {
return JSON.stringify(postData);
},
jsonReader: {
id: "Id",
root: function(obj) { return obj.rows; },
page: function(obj) { return obj.page; },
total: function(obj) { return obj.total; },
records: function(obj) { return obj.records; }
},
headertitles: true,
search: true,
rowNum: 15, // - rows per page
rowList: [5, 10, 15, 20], // - options for rows per page
pager: "#pager", // - element anchor for navigation panel
gridview: true, // - row at once binding (faster performance)
autoencode: true, // - encode html data
ignoreCase: true, // - searches are case-insensitive
//sortname: "IDNumber", // - sort column for initial load
viewrecords: true, // - displays the beginning and ending record number in the grid, out of the total number of records in the query
sortorder: "asc",
caption: "Card Personalization",
height: "100%",
shrinkToFit: false, // - defines how the width of the columns of the grid should be re-calculated, taking into consideration the width of the grid
autowidth: true,
multiselect: false,
loadui: "disable",
colNames: ["IDType", "IDNumber", "LastName", "FirstName", "MiddleInitial", "EmbossLine1", "EmbossLine2", "Address1", "Address2", "Address3", "City", "Country", "State",
"PostalCode", "DateOfBirth", "EmailAddress", "HomePhone", "OfficePhone", "MobilePhone", "PhotoReference", "SalaryID", "SolID", "IDImage", "ErrorCells", "ErrorDescriptions", "IDThumb"],
colModel: [
{ name: "IDType", width: 80, align: "left", editable: true, sortable: true, sorttype: "integer",
stype: "select",
edittype: "select",
formatter: "select",
formoptions: { elmprefix: "<font color='red'>*</font>" },
searchoptions: { sopt: ["eq"], value: GetIdTypes(true) },
editrules: { required: true, integer: true, minValue: 1, maxValue: 50 },
editoptions: { value: GetIdTypes(false), dataInit: function(elem) { $(elem).width(150); } },
searchOptions: { defaultValue: 4 },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(0, rawObject); }
},
{ name: "IDNumber", width: 80, align: "left", editable: true, sortable: true,
editrules: { required: true, custom: true, custom_func: validateIDNumber },
editoptions: { maxlength: 30 },
formoptions: { elmprefix: "<font color='red'>*</font>" },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(1, rawObject); }
},
{ name: "LastName", width: 100, align: "left", editable: true, sortable: true,
editrules: { required: true, custom: true, custom_func: validateName },
editoptions: { maxlength: 200 },
formoptions: { elmprefix: "<font color='red'>*</font>" },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(2, rawObject); }
},
{ name: "FirstName", width: 100, align: "left", editable: true, sortable: true,
editrules: { required: true, custom: true, custom_func: validateName },
editoptions: { maxlength: 200 },
formoptions: { elmprefix: "<font color='red'>*</font>" },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(3, rawObject); }
},
{ name: "MiddleInitial", width: 70, align: "left", editable: true, sortable: true, search: false,
editrules: { required: false, custom: true, custom_func: validateName },
editoptions: { maxlength: 40 },
formoptions: { elmprefix: " " },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(4, rawObject); }
},
{ name: "EmbossLine1", width: 100, align: "left", editable: true, sortable: true, search: false,
editrules: { required: $('#cbFirstLineEmbossing').prop('checked'), custom: true, custom_func: validateEmbossline },
editoptions: { maxlength: 19, dataInit: function(el) { $(el).css('text-transform', 'uppercase'); } },
formoptions: { elmprefix: "<font color='red'>*</font>" },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(5, rawObject); }
},
{ name: "EmbossLine2", width: 100, align: "left", editable: true, sortable: true, search: false,
editrules: { required: $('#cbSecondLineEmbossing').prop('checked'), custom: true, custom_func: validateEmbossline },
editoptions: { maxlength: 19, dataInit: function(el) { $(el).css('text-transform', 'uppercase'); } },
formoptions: { elmprefix: "<font color='red'>*</font>" },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(6, rawObject); }
},
{ name: "Address1", width: 200, align: "left", editable: true, sortable: true, search: false,
editrules: { required: true, custom: true, custom_func: validateAddress },
editoptions: { maxlength: 50 },
formoptions: { elmprefix: "<font color='red'>*</font>" },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(7, rawObject); }
},
{ name: "Address2", width: 200, align: "left", editable: true, sortable: true, search: false,
editrules: { required: false, custom: true, custom_func: validateAddress },
editoptions: { maxlength: 50 },
formoptions: { elmprefix: " " },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(8, rawObject); }
},
{ name: "Address3", width: 200, align: "left", editable: true, sortable: true, search: false,
editrules: { required: false, custom: true, custom_func: validateAddress },
editoptions: { maxlength: 50 },
formoptions: { elmprefix: " " },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(9, rawObject); }
},
{ name: "City", width: 100, align: "left", editable: true, sortable: true,
editrules: { required: true, custom: true, custom_func: validateCity },
editoptions: { maxlength: 50 },
formoptions: { elmprefix: "<font color='red'>*</font>" },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(10, rawObject); }
},
{ name: "Country", width: 50, align: "left", editable: true, edittype: "select", stype: "select", sortable: true,
editrules: { required: true, custom: true, custom_func: validateCountry },
formoptions: { elmprefix: "<font color='red'>*</font>" },
searchoptions: {
value: GetCountries(true),
dataInit: function(elem) {
var v = $(elem).val();
if (v !== '')
setStateValues(v, true);
},
dataEvents: [
{ type: "change", fn: function(e) { changeStateSelect($(e.target).val(), e.target); } },
{ type: "keyup", fn: function(e) { $(e.target).trigger('change'); } }
]
},
editoptions: {
maxlength: 2,
value: GetCountries(false),
dataInit: function(elem) { // - populate the state dropdown based on selected country
var v = $(elem).val();
if (v !== '')
setStateValues(v, false);
setTimeout(function() {
var $element = $(elem),
required = $element.val() === 'US';
$grid.jqGrid('setColProp', 'PostalCode', { editrules: { required: required} });
$('#PostalCode').siblings('.mystar').html(required ? '*' : ' ');
$element.width(150);
}, 100);
},
dataEvents: [
{ type: "change", fn: function(e) {
changeStateSelect($(e.target).val(), e.target);
var required = $(e.target).val() === 'US';
$grid.jqGrid('setColProp', 'PostalCode', { editrules: { required: required} });
$('#PostalCode').siblings('.mystar').html(required ? '*' : ' ');
}
},
{ type: "keyup", fn: function(e) { $(e.target).trigger('change'); } }
]
},
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(11, rawObject); }
},
{ name: "State", width: 50, align: "left", editable: true, edittype: "select", stype: "select", sortable: true,
editrules: { required: true, custom: true, custom_func: validateState },
formoptions: { elmprefix: "<font color='red'>*</font>" },
editoptions: {
value: {},
maxlength: 4,
dataInit: function(elem) { $(elem).width(150); }
},
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(12, rawObject); }
},
{ name: "PostalCode", width: 70, align: "left", editable: true, sortable: true, search: false,
editrules: { required: false, custom: true, custom_func: validatePostal },
editoptions: { maxlength: 30 },
formoptions: { elmprefix: "<span class='mystar' style='color:red'> </span>" },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(13, rawObject); }
},
{ name: "DateOfBirth", width: 80, align: "left", editable: true, sortable: true, sorttype: "date", search: false,
editrules: { required: true, date: true, custom: true, custom_func: validateDate },
formoptions: { elmprefix: "<font color='red'>*</font>", elmsuffix: " format: mm/dd/yyyy" },
editoptions: {
size: 10,
maxlength: 10,
dataInit: function(element) {
$(element).datepicker({
dateFormat: "mm/dd/yy", changeMonth: true, changeYear: true, yearRange: "-100y:c+nn", maxDate: "-1d"
}).mask('99/99/9999');
}
},
datefmt: 'mm/dd/yyyy',
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(14, rawObject); }
},
{ name: "EmailAddress", width: 150, align: "left", editable: true, sortable: true, search: false,
editrules: { required: false, custom: true, custom_func: validateEmail },
editoptions: { maxlength: 100 },
formoptions: { elmprefix: " " },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(15, rawObject); }
},
{ name: "HomePhone", width: 100, align: "left", editable: true, sortable: true, search: false,
editrules: { required: false, custom: true, custom_func: validatePhone },
editoptions: { maxlength: 30 },
formoptions: { elmprefix: " " },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(16, rawObject); }
},
{ name: "OfficePhone", width: 100, align: "left", editable: true, sortable: true, search: false,
editrules: { required: false, custom: true, custom_func: validatePhone },
editoptions: { maxlength: 30 },
formoptions: { elmprefix: " " },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(17, rawObject); }
},
{ name: "MobilePhone", width: 100, align: "left", editable: true, sortable: true,
editrules: { required: true, custom: true, custom_func: validatePhone },
editoptions: { maxlength: 30 },
formoptions: { elmprefix: "<font color='red'>*</font>" },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(18, rawObject); }
},
{ name: "PhotoReference", width: 100, align: "left", editable: true, sortable: true, search: false,
editrules: { required: true },
editoptions: { maxlength: 30 },
formoptions: { elmprefix: "<font color='red'>*</font>" },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(19, rawObject); }
},
{ name: "SalaryID", width: 100, align: "left", editable: true, sortable: true, search: true,
editrules: { required: false, custom: true, custom_func: validateSalaryIdLocal },
editoptions: { maxlength: 30 },
formoptions: { elmprefix: " " },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(20, rawObject); }
},
{ name: "SolID", width: 50, align: "left", editable: true, sortable: true, edittype: "select", stype: "select",
editrules: { required: true /*, custom: true, custom_func: validateSolId*/ },
editoptions: { value: GetSolIds(_selectedConfiguration, false), maxlength: 4 },
searchoptions: { sopt: ["eq"], value: GetSolIds(_selectedConfiguration, true) },
formoptions: { elmprefix: "<font color='red'>*</font>" },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(21, rawObject); }
},
{ name: "IDImage", width: 100, align: "left", editable: true, sortable: true, search: true,
editrules: { required: false, custom: true, custom_func: _validateIDImagePath },
editoptions: { maxlength: 150, readonly: true },
formoptions: { elmprefix: " " },
cellattr: function(rowId, tv, rawObject, cm, rdata) { return SetCellError(22, rawObject); }
},
{ name: "ErrorCells", hidden: true, editoptions: { defaultValue: '0'} },
{ name: "ErrorDescriptions", hidden: true },
{ name: "IDThumb", width: 50, fixed: true,
formatter: function(cellvalue, options, rowObject) {
return '<a id="imgSource_' + options.rowId + '" href="" data-lightbox="image_' + options.rowId + '" data-title=""><img id="imgThumb_' + options.rowId + '" src="" width="30" height="30"></a>';
}
}],
ondblClickRow: function(rowid, ri, ci) { // - double click event handler
var p = $grid[0].p;
if (p.selrow !== rowid) // prevent the row from be unselected on double-click
$grid.jqGrid('setSelection', rowid);
$grid.jqGrid('editGridRow', rowid, editSettings); // - form edit
},
onSelectRow: function(id) { // - select row event handler
if (id && id !== lastSel) {
$grid.jqGrid('restoreRow', lastSel);
lastSel = id;
}
},
beforeRequest: function() { // - on initial load, display empty grid for editing
if (_initialLoad)
$grid.jqGrid('setGridParam', { datatype: "local", loadonce: false });
},
loadError: function(xhr, st, errorThrown) { // - todo: handle error from server during load, need to spruce this up
_initialDataLoad = false;
$('#fileUploadOK').hide();
ShowButtons(false, IsGridValid()); // - refresh button states if grid is loaded
$grid.jqGrid('setGridParam', { datatype: "local", loadonce: false }); // - fail, lets rebind an empty grid for manual entry
Toggle(true); // - slide toggle the top section open
},
loadComplete: function(data) {
$('#filterInvalid').prop('disabled', false);
$grid.jqGrid('hideCol', 'cb'); // - hide the check boxes for multi-select
if (_initialLoad) { // - set the column header tooltips on initial empty bind
setTooltipsOnColumnHeader($grid, 1, 'IDType (required)\nExample:\n1: International Passport\n2: National ID\n3: Drivers License\n4: Other ');
setTooltipsOnColumnHeader($grid, 2, 'IDNumber (required)\nIDNumber for corresponding IDType.\nMax length 30.');
setTooltipsOnColumnHeader($grid, 3, 'LastName (required)\nMax length 50.');
setTooltipsOnColumnHeader($grid, 4, 'FirstName (required)\nMax length 50.');
setTooltipsOnColumnHeader($grid, 5, 'MiddleInitial (optional)\nMax length 40.');
setTooltipsOnColumnHeader($grid, 6, 'EmbossLine1 (optional)\nThis is the text to be embossed on the first line of the card. If it is blank, it will default to the FirstName LastName.\nMax length 19.');
setTooltipsOnColumnHeader($grid, 7, 'EmbossLine2 (optional)\nIf 2nd Line Embossing is needed, specify the value here with no more than 19 characters and inform GTP that 2nd line embossing is requested for the order. (Note: not all vendors are able to emboss line 2)\nMax length 19.');
setTooltipsOnColumnHeader($grid, 8, 'Address1 (required)\nMax length 50.');
setTooltipsOnColumnHeader($grid, 9, 'Address2 (optional)\nMax length 50.');
setTooltipsOnColumnHeader($grid, 10, 'Address3 (optional)\nMax length 50.');
setTooltipsOnColumnHeader($grid, 11, 'City (required)\nMax length 50.');
setTooltipsOnColumnHeader($grid, 12, 'Country (required)\nSee CountryCodeList sheet for valid Country codes\nMax length 2.');
setTooltipsOnColumnHeader($grid, 13, 'State (required)\nSee StateCountryCodeList sheet for valid State/Country combinations.');
setTooltipsOnColumnHeader($grid, 14, 'PostalCode (optional)\nRequired for US addresses.\nMax length 30.');
setTooltipsOnColumnHeader($grid, 15, 'DateOfBirth (required)\nMM/DD/YYY format.');
setTooltipsOnColumnHeader($grid, 16, 'EmailAddress (optional)\nMax length 100.');
setTooltipsOnColumnHeader($grid, 17, 'HomePhone (optional)\nPrefix with country code; no leading zeros.\nMax length 30.');
setTooltipsOnColumnHeader($grid, 18, 'OfficePhone (optional)\nPrefix with country code; no leading zeros.\nMax length 30.');
setTooltipsOnColumnHeader($grid, 19, 'MobilePhone (required)\nPrefix with country code; no leading zeros.\nMax length 30.');
setTooltipsOnColumnHeader($grid, 20, 'Photo Reference (required for Photo Card orders.\nMax length 30.');
setTooltipsOnColumnHeader($grid, 21, 'SalaryID (optional)\nCan be used for account or for picture id to map to a jpeg file.\nMax length 30.');
setTooltipsOnColumnHeader($grid, 22, 'SolID (required by some banks)\nFour digit value with leading zeros.');
setTooltipsOnColumnHeader($grid, 23, 'IDImage (optional)\nName of associated ID image file.');
_initialLoad = false;
} else
$('#txtCardCount').val($grid.getGridParam('records')); // - set the total card count
refreshIDImages();
if (_selectedConfiguration) {
ZapColumn($grid, 'SolID', _selectedConfiguration.MYISBRANCHIDREQ === 'N');
ZapColumn($grid, 'PhotoReference', !$('#cbPhotoID').prop('checked'));
}
if (_initialDataLoad) {
IsImageUploadValid();
$('#fileUploadOK').show(); // - display upload status
var setErrors = new GridErrors($grid);
setErrors.setEmboss = true;
setErrors.setPhotoReference = true;
setErrors.setSolID = true;
setErrors.execute();
}
var gridValid = IsGridValid();
ShowButtons(true, gridValid);
if (_initialDataLoad) {
ResetFilter(gridValid);
$grid.trigger('reloadGrid', [{ page: 1}]);
}
_initialDataLoad = false;
}
}).jqGrid('navGrid', '#pager', { refresh: false, search: false }, editSettings, addSettings, delSettings, {
multipleSearch: true,
overlay: false,
onClose: function(form) {
// if we close the search dialog while the datepicker is open
// the datepicker will stay opened. To fix this we have to hide
// the div used by datepicker
$('div#ui-datepicker-div.ui-datepicker').hide();
}
}).jqGrid('filterToolbar', {
stringResult: true,
searchOnEnter: false,
beforeSearch: function() { return false; }
}); //.jqGrid('setFrozenColumns'); // - this freezes columns during horiz. scrolling
}
This is the data (kind of, just showing an example of ErrorCells)
Any advice appreciated, thanks.
The problem seems to me independent from the used jQuery version. The reason of described problem is the usage of old style filter
$.extend(postdata, { // - set filter condition
filters: '',
searchField: 'ErrorCells',
searchOper: 'ne',
searchString: '0'
});
instead of new-style filter
$.extend(postdata, { // - set filter condition
filters: JSON.stringify({
groupOp: "AND",
groups: [],
rules: [{field: "ErrorCells", op: "ne", data: "0"}]
})
});
or
$.extend(postdata, { // - set filter condition
filters: {
groupOp: "AND",
groups: [],
rules: [{field: "ErrorCells", op: "ne", data: "0"}]
}
});
By the way you use multipleSearch: true and the old style filter could not be displayed.
Nevertheless free jqGrid should in general work with old style filter too. I fixed the problem and posted the commit to GitHub. You need to download the latest sources from GitHub.
Thank you for reporting the bug!
Please verify that the problem is fixed with the latest sources, but after that I would recommend you to change the old-style filter to the new-style (see the code above).
Related
After row saved call back in jqgrid
I need to able to tap into an event after row has been updated, I use inline editing. There is a beforeSend event in ajaxRowOptions but no matching after. How do I implement an after save callback? Here is my grid: $('#myGrid').jqGrid({ datatype: 'local', jsonReader: common.jqgrid.jsonReader('Code'), editurl: common.getServerPath() + 'myAjax/updateSomething/', ajaxRowOptions: { beforeSend: function (jqXhr, settings) { //something here } } }, mtype: 'POST', pager: '#myPager', colNames: ['Method', 'Type', 'Package', 'Disc %'], colModel: [ { name: 'Code', index: 'Code', width: 25, sortable: false }, { name: 'MethodType', index: 'MethodType', width: 10, sortable: false, align: 'center' }, { name: 'ProfNo', index: 'ProfNo', width: 15, sortable: false, align: 'center' }, { name: 'Discount', index: 'Discount', width: 15, sortable: false, edittype: 'text', align: 'right', editable: true, editrules: { number: false, custom: true, custom_func: validateDiscount } }], scroll: true, hidegrid: false, altRows: true, altclass: 'gridAltRowClass', height: 330, scrollOffset: 0, width: 770, rowNum: 500, footerrow: true, userDataOnFooter: true }); and validateDiscount: function (value) { if (isNaN(value)) { return [false, 'Discount must be a number.']; } else { var numValue = parseFloat(Number(value).toFixed(2)); if (numValue >= 100.00) { return [false, 'is not a valid value. Discount must be a number less than 100.']; } } return [true, '']; },
JQGrid displaying wrong date when formatted
I have a JQGrid that is built using a jsonReader, with a field called quote_date. When this field is not formatted, it displays the value "19/04/2020 00:00:00" Code for unformatted field name: 'quote_date', index: 'quote_date', width: 100, editable: true However when I try to use the JQGrid formatter (I am trying to remove the trialing zero's), the date value in the grid is disaplyed as "10-10-2024" ! Here is the code I am using to format the field name: 'quote_date', formatter: 'date', datefmt: "d-M-Y", editoptions: { dataInit: initDateEdit }, formatoptions: { srcformat: "ISO8601Long", newformat: "d-m-Y" }, index: 'quote_date', width: 100, editable: true The expected result is "19/04/2020" I have check the returned JSON result and that is correct as per the below. Here is my complete code to give some context. Code to build grid function LoadGrid() { jQuery("#jqquotes").jqGrid({ url: '../WebService1.asmx/getDataQuotes', datatype: "json", mtype: 'POST', ajaxGridOptions: { contentType: "application/json" }, serializeGridData: function (postData) { return JSON.stringify(postData); }, jsonReader: { root: function (obj) { return typeof obj.d === "string" ? $.parseJSON(obj.d) : obj.d; }, repeatitems: false }, loadComplete: function () { //alert("OK"); }, 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); }, onSelectRow: showDetailsGrid, height: 'auto', //autowidth: true, rowNum: 30, rowList: [10, 20, 30], colNames: ['Doc ID', 'Quote #', 'Date', 'Customer'], colModel: [ { name: 'docid', key: true, index: 'docid', width: 55, editable: true }, { name: 'quote_number', index: 'quote_number', width: 90, editable: true }, { name: 'quote_date', formatter: 'date', datefmt: "d-M-Y", editoptions: { dataInit: initDateEdit }, formatoptions: { srcformat: "ISO8601Long", newformat: "d-m-Y" }, index: 'quote_date', width: 100, editable: true //name: 'quote_date', index: 'quote_date', width: 100, editable: true }, { name: 'cust_name', index: 'cust_name', width: 80, align: "left", editable: true, edittype: "select", editoptions: { value: {} } } ], pager: "#jqquotesPager", viewrecords: true, caption: "Quotes", gridview: true, loadonce: false, //Important - Doesn't work without - might need server side paging? }).navGrid('#jqquotesPager', { edit: true, add: true, del: true }, // options { url: '../WebService1.asmx/modifyDataQuotes', closeAfterEdit: true, beforeShowForm: function (form) { $('#docid', form).attr("disabled", true); }, ajaxEditOptions: { contentType: "application/json" }, recreateForm: true, serializeEditData: function (postData) { if (postData.exercise_value === undefined) { postData.exercise_value = null; } return JSON.stringify(postData); } }, // edit options { url: "../WebService1.asmx/addDataQuotes", closeAfterAdd: true, beforeShowForm: function (form) { $('#docid', form).attr("disabled", true); }, ajaxEditOptions: { contentType: "application/json" }, recreateForm: true, serializeEditData: function (postData) { if (postData.exercise_value === undefined) { postData.exercise_value = null; } return JSON.stringify(postData); } }, // add options { url: "../WebService1.asmx/deleteDataQuotes", ajaxDelOptions: { contentType: "application/json" }, serializeDelData: function (postData) { if (postData.exercise_value === undefined) { postData.exercise_value = null; } return JSON.stringify(postData); } }, //del options { multipleSearch: true, recreateFilter: true, closeOnEscape: true, overlay: false }, // search options ); } Code for Datepicker //Define Datepicker $grid = $("#jqquotes"), initDateEdit = function (elem) { $(elem).datepicker({ dateFormat: "dd-mm-yy", autoSize: true, changeYear: true, changeMonth: true, showButtonPanel: true, showWeek: true }); }, initDateSearch = function (elem) { var $self = $(this); setTimeout(function () { $(elem).datepicker({ dateFormat: "dd-mm-yy", autoSize: true, changeYear: true, changeMonth: true, showWeek: true, showButtonPanel: true, onSelect: function () { if (this.id.substr(0, 3) === "gs_") { // call triggerToolbar only in case of searching toolbar setTimeout(function () { $self[0].triggerToolbar(); }, 100); } } }); }, 100); }, numberTemplate = { formatter: "number", align: "right", sorttype: "number", editrules: { number: true, required: true }, searchoptions: { sopt: ["eq", "ne", "lt", "le", "gt", "ge", "nu", "nn", "in", "ni"] } }; I have spent about half a day on this, but cannot for the life of me figure out whats happening. Any help greatly appreciated.
There is a not correct setting in the srcformat and the actual format that come from the data source. By definition the ISO8601Long is described like : ISO8601Long:"Y-m-d H:i:s", See here Your source data format is d/m/Y H:i:s, which is quite different. In order this to worku set it like this: ... { name: 'quote_date', formatter: 'date', datefmt: "d-m-Y", editoptions: { dataInit: initDateEdit }, formatoptions: { srcformat: "d/m/Y H:i:s", newformat: "d-m-Y" }, index: 'quote_date', width: 100, editable: true }, Note that I have changed the datefmt and newformat in case you want to remove the trailing zero's. This will be compatible with your datepicker settings
jqGrid dropdown has wrong value on edit form
One of the three dropdowns on my edit form is not being set correctly when the form opens. The two other dropdowns on the form are properly set. The dropdown data is being returned from the server in the form of <select><option value='#'>blah</option></select>. classDesc, purchClass and company are three fields using a dropdown on the edit form. All display correctly on the grid, but on the edit form company always displays the first option. The value shown in the column on the grid is present in the dropdown data returned from the server but it's not being selected. (See screenshot) I've tried forcing the value in afterShowForm, but that has no effect. jqGrid 4.6.0 Here's my column model: colModel : [ { name:'id', index:'id', width:50, sortable:true, hidden: false, editable: true, align: 'right', editrules: {edithidden: false}, searchoptions: { sopt: ['eq','bw', 'cn']}, editrules: {required:true}}, { name:'submittable', index:'submittable', width:42,sortable:false, align: 'center', search: false, cellattr: function () { return ' title="Submit this order"'; }}, { name:'statusId', index:'statusId', width:50, sortable:false, hidden: true, editable: true, editrules: {edithidden: false}}, { name:'statusClassId', index:'statusClassId', width:50, sortable:false, hidden: true, editable: true, editrules: {edithidden: false}}, { name:'status', index:'status', width:100, sortable:true, hidden: false, editable:true, editoptions:{readonly:"true", defaultValue:"Open"}, searchoptions: { sopt: ['eq','bw', 'cn']}, editrules: {required:true}}, { name:'dlcd', index:'dlcd', width:50, sortable:true, hidden: false, editable:true, editoptions:{readonly: true, defaultValue:"<%=userDatabean.getNumber()%>"}, searchoptions: { sopt: ['eq','bw', 'cn']}, editrules: {required:true}}, { name:'classId', index:'classId', width:10, sortable:false, hidden: true, editable: true, editrules: {edithidden: false}}, { name:'classDesc', index:'classDesc', width:75, sortable:true, editable:true, edittype:'select', editoptions: {dataUrl:'/rebate/rest/lookup/v1/getClass'}, searchoptions: { sopt: ['eq','bw', 'cn']}, editrules: {required:true}}, { name:'purchClassId', index:'purchClassId', width:10, sortable:false, hidden: true, editable: true, editrules: {edithidden: false}}, { name:'purchClass', index:'purchClass', width:70, sortable:true, editable:true, edittype:'select', editoptions: { dataUrl:'/rebate/rest/lookup/v1/getPurch'}, searchoptions: { sopt: ['eq','bw', 'cn']}, editrules: {required:true}}, { name:'purchOther', index:'purchOther', width:150, sortable:false, hidden: true, editable:true, editrules: {edithidden: true}}, { name:'custId', index:'custId', width:30, sortable:false, hidden: false, editable: true, editrules: {edithidden: false}}, { name:'company', index:'company', width:175, sortable:true, editable:true, edittype:'select', editoptions: {dataUrl:'/rebate/rest/lookup/v1/getCustomer'}, searchoptions: { sopt: ['eq','bw', 'cn']}, editrules: {required:true}}, { name:'poNum', index:'poNum', width:15, sortable:false, hidden: true, editable:true, editrules: {edithidden: true}}, { name:'deliveryDate', index:'deliveryDate', width:80, sortable:true, hidden: false, editable:true, sorttype: "integer", formatter: function (cellValue, options, rowdata, action) { var date = new Date(cellValue); var year = date.getFullYear(); var month = date.getMonth() < 9 ? "0" + (date.getMonth()+1) : (date.getMonth()+1); var day = date.getDate() <=9 ? "0" + date.getDate() : date.getDate(); return [year,month,day].join("-"); }, searchoptions: { sopt: ['eq','bw', 'cn']}, editrules: {required:true}, editoptions: { maxlength: 12, dataInit: function(element){ $(element).datepicker({ dateFormat: "yy-mm-dd" }) } }, editrules: { date: true, required: false }, editrules: {required:true}}, { name:'dlrInfo', index:'dlrInfo', width:15, sortable:false, hidden: true, editable:true, editrules: {edithidden: true}, editoptions:{size:50, maxlength: 100}}, { name:'file1', index: 'file1', width:50, sortable:false, hidden: true, editable: true, editrules: {edithidden: true}}, { name:'file2', index: 'file2', width:50, sortable:false, hidden: true, editable: true, editrules: {edithidden: true}}, { name:'terms', index:'terms', width:50, sortable:false, hidden: true, editable: true, edittype:'checkbox', editoptions: {value:"true:false"}, editrules: {edithidden: true}, formoptions:{label: 'Terms'} }, ], And the navGrid w/the edit parameters: $("#orderGrid").jqGrid('navGrid', '#orderGridPager', { edit : true, add : true, del : false, search : true },{ //Edit form url : '/rebate/rest/header/v1/update', width: 600, viewPagerButtons: false, closeAfterEdit: true, recreateForm: true, modal: true, beforeShowForm: function ($form) { if($('#file1').val()=='') { //no file so add the file inputs $('#tr_file1').html('<td class="CaptionTD">Receipt 1</td><td class="DataTD"> <input type="file" enctype="multipart/form-data" id="file1" name="file1" class="FormElement"></td>'); $('#tr_file2').html('<td class="CaptionTD">Receipt 2</td><td class="DataTD"> <input type="file" enctype="multipart/form-data" id="file2" name="file2" class="FormElement"></td>'); } else { //we have a file so just show the file name $('#tr_file1').html('<td class="CaptionTD">Receipt 1</td><td class="CaptionTD"> ' + $('#file1').val() +'</td>'); $('#tr_file2').html('<td class="CaptionTD">Receipt 2</td><td class="CaptionTD"> ' + $('#file2').val() +'</td>'); } $form.find("#status,#dlcd,#id") .prop("readonly", true) .addClass("ui-state-disabled"); if(!security[userLevel][$("#statusClassId").val()-1]) { //make all fields read only. $form.find("input,select,button") .prop("disabled", true) .addClass("ui-state-disabled") .closest(".DataTD") .prev(".CaptionTD") .prop("disabled", true); $form.parent().find('#sData').hide(); } }, afterShowForm: function(formId) { $("#company").val($("#custId").val()).prop("select",true); console.log("after custId: " + $("#custId").val()); }, beforeSubmit: function(postdata, formid) { var chk = checkBeforeSubmit(); if(!chk[0]) return chk; return [true, null, null]; }, serializeEditData: function (postdata) { return getFieldData("FrmGrid_orderGrid"); }, afterSubmit: function(response, postdata) { sendFormFiles(response.responseText); //console.log(response); $('#grid').trigger( 'reloadGrid' ); return [true,null,null]; }, errorTextFormat: function(response) { return response.responseText=="" ?"400.1: An unknown error occured." : response.responseText; } }
This turned out to be a data issue. The query to populate the grid pulled in just the company name, the query for the lookup to build the dropdown was concatenating a few other fields into the display value. I assumed jqgrid would use the custId value to select the right element in the dropdown but it's using the display value.
How to get jqGrid rows in json objects after applying search filter
I have added a search textbox which allows users to perform search on all rows and columns now i want to get all the filtered rows in json format so i can generate a report. Below is the code for Jqgrid var grid = $("#jqGrid"); grid.jqGrid({ url: 'VehicleMaster.aspx/GetLoadData', mtype: 'POST', datatype: 'json', ajaxGridOptions: { contentType: 'application/json; charset=utf-8' }, serializeGridData: function(postData) { return JSON.stringify(postData); }, ajaxSelectOptions: { type: "GET" }, jsonReader: { repeatitems: false, root: function(obj) { return JSON.parse(obj.d); } }, loadonce: true, sortable: true, shrinkToFit: false, autowidth: true, rowNum: 25, rowList: [15, 25, 50, 75, 100], viewsortcols: [true, 'vertical', true], pager: '#pager', pgtext: "Page from {0} to {1}", styleUI: 'Bootstrap', height: $(window).height() - (343), //DYNAMIC HEIGHT loadComplete: function() { $(this).find(" > tbody > tr.jqgrow:odd").addClass("altRowClassEven"); $(this).find(" > tbody > tr.jqgrow:even").addClass("altRowClassOdd"); }, colNames: gridColumnNames, //FROM BACKEND colModel: [ { label: 'Id', name: 'Id', width: 130, editable: false, hidden: true }, { label: 'VehicleName', name: 'VehicleName', width: 130, editable: false }, { label: 'PlateCode', name: 'PlateCode', editable: true, width: 100 }, { label: 'PlateNo', name: 'PlateNo', editable: true, width: 100, editoptions: { dataInit: function(domElem) { $(domElem).keyup(function() { this.value = this.value.replace(/[^0-9\.]/g, ''); }); } } }, { label: 'Owner', name: 'Owner', editable: true, width: 100 }, { label: 'Brand', name: 'Brand', editable: true, width: 100 }, { label: 'Color', name: 'Color', editable: true, width: 100 }, { label: 'Make', name: 'Make', editable: true, width: 100 }, { label: 'Model', name: 'Model', editable: true, width: 100 }, { label: 'YearModel', name: 'YearModel', editable: true, width: 100 }, { label: 'Seats', name: 'Seats', editable: true, width: 100, editoptions: { dataInit: function(domElem) { $(domElem).keyup(function() { this.value = this.value.replace(/[^0-9\.]/g, ''); }); } } }, { label: 'Doors', name: 'Doors', editable: true, width: 100, editoptions: { dataInit: function(domElem) { $(domElem).keyup(function() { this.value = this.value.replace(/[^0-9\.]/g, ''); }); } } }, { label: 'RegistrationDate', name: 'RegistrationDate', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); //$(domElem).inputmask('99/99/9999'); } } }, { label: 'RegistrationExpiry', name: 'RegistrationExpiry', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); } } }, { label: 'ChassisNo', name: 'ChassisNo', editable: true, width: 100 }, { label: 'EngineNo', name: 'EngineNo', editable: true, width: 130 }, { label: 'TrafficFileNo', name: 'TrafficFileNo', editable: true, width: 130 }, { label: 'VehicleType', name: 'VehicleType', editable: true, width: 130 }, { label: 'InsuranceCompany', name: 'InsuranceCompany', editable: true, width: 160 }, { label: 'InsuranceDate', name: 'InsuranceDate', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); } } }, { label: 'InsuranceExpiry', name: 'InsuranceExpiry', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); } } }, { label: 'PlateIssueDate', name: 'PlateIssueDate', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); } } }, { label: 'Department', name: 'Department', editable: true, width: 130 }, { label: 'Description', name: 'Description', editable: true, width: 130 }, { label: 'Column1', name: 'Column1', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); } } }, { label: 'Column2', name: 'Column2', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); } } }, { label: 'Column3', name: 'Column3', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); } } }, { label: 'Column4', name: 'Column4', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); } } }, { label: 'Column5', name: 'Column5', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); } } }, { label: 'Column6', name: 'Column6', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); } } }, { label: 'Column7', name: 'Column7', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); } } }, { label: 'Column8', name: 'Column8', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); } } }, { label: 'Column9', name: 'Column9', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); } } }, { label: 'Column10', name: 'Column10', editable: true, width: 130, editoptions: { dataInit: function(domElem) { $(domElem).datepicker({ format: 'dd/mm/yyyy', autoclose: true, clearBtn: true }); $(domElem).prop('readonly', true); } } } ], multiselect: false, cellEdit: true, hiddengrid: false, loadtext: 'Loading Data...', sortascimg: 'sort_asc.gif', sortdescimg: 'sort_desc.gif', cellsubmit: 'clientArray', viewrecords: true, beforeSelectRow: function(rowid) { console.log(rowid); if (typeof selectedRows[0] !== "undefined") { updateSelectedRow(selectedRows[selectedRows.length - 1]); console.log(selectedRows[selectedRows.length - 1]); } selectedRows.push(rowid); } }); Below is the code for live search. $("#globalSearchText").keyup(function() { var rules = [], i, cm, postData = grid.jqGrid("getGridParam", "postData"), colModel = grid.jqGrid("getGridParam", "colModel"), searchText = $("#globalSearchText").val(), l = colModel.length; for (i = 0; i < l; i++) { cm = colModel[i]; if (cm.search !== false && (typeof cm.stype === "undefined" || cm.stype === "text")) { rules.push({ field: cm.name, op: "cn", data: searchText }); } } $.extend(postData, { filters: { groupOp: "OR", rules: rules } }); Kindly guide me to resolve this. Thanks
Jqgrid keep focus on current cell when using editrules
First, I'm going to be submitting a couple of different questions that relate to the code snippet posted here. So, if you see other questions and think "hey, that's a duplicate, I've seen that code" it really isn't. I want to be sure to credit each answerer for the distinctly different questions. Here's one: I have the following jqgrid, and I'm trying to change the masking from "__" to "00" when the user only enters the first half of the field. The method gets called, the value changed, but it still displays the old value. I'm using jqgrid version 4.2. Grid: WorkSchedule.prototype.init = function() { var self = this; self.jqgridParms = { datatype: "local", height: 'auto', width: 700, colNames: ["Week", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Total"], colModel: [// very much dummy stuff here. {name: "Week", index: "Week", width: 50, editable: false }, { name: "Sun", index: "Sun", width: 85, editable: true, edittype: "text", editoptions: { size: 20, maxlength: 30, dataInit: function(elem) { $(elem).mask("99:99"); } }, align: "center", formatter: timeEntryFormat, editrules: { custom: true, custom_func: validHourEntry } }, { name: "Mon", index: "Mon", width: 85, editable: true, edittype: "text", editoptions: { size: 20, maxlength: 30, dataInit: function(elem) { $(elem).mask("99:99"); } }, align: "center", formatter: timeEntryFormat, editrules: { custom: true, custom_func: validHourEntry } }, { name: "Tues", index: "Tues", width: 85, editable: true, edittype: "text", editoptions: { size: 20, maxlength: 30, dataInit: function(elem) { $(elem).mask("99:99"); } }, align: "center", formatter: timeEntryFormat, editrules: { custom: true, custom_func: validHourEntry } }, { name: "Wed", index: "Wed", width: 85, editable: true, edittype: "text", editoptions: { size: 20, maxlength: 30, dataInit: function(elem) { $(elem).mask("99:99"); } }, align: "center", formatter: timeEntryFormat, editrules: { custom: true, custom_func: validHourEntry } }, { name: "Thurs", index: "Thurs", width: 85, editable: true, edittype: "text", editoptions: { size: 20, maxlength: 30, dataInit: function(elem) { $(elem).mask("99:99"); } }, align: "center", formatter: timeEntryFormat, editrules: { custom: true, custom_func: validHourEntry } }, { name: "Fri", index: "Fri", width: 85, editable: true, edittype: "text", editoptions: { size: 20, maxlength: 30, dataInit: function(elem) { $(elem).mask("99:99"); } }, align: "center", formatter: timeEntryFormat, editrules: { custom: true, custom_func: validHourEntry } }, { name: "Sat", index: "Sat", width: 85, editable: true, edittype: "text", editoptions: { size: 20, maxlength: 30, dataInit: function(elem) { $(elem).mask("99:99"); } }, align: "center", formatter: timeEntryFormat, editrules: { custom: true, custom_func: validHourEntry } }, { name: "WeekTotal", index: "WeekTotal", width: 55, editable: true, align: "center" } ], multiselect: false, caption: "Manage Work Schedule", rowNum: 10, cellEdit: true, gridComplete: function() { calculateTotal(); }, beforeSaveCell: function(rowid,cellname,value,iRow,iCol) { formatFromMask(rowid, cellname, value, iRow, iCol); }, afterSaveCell: function() { calculateTotal(); }, cellsubmit: "clientArray" } } function formatFromMask(rowid, cellname, value, iRow, iCol) { if (typeof value !== "undefined") { value = value.replace(/_/g, "0"); return value; } }
Ok, I found the simple answer, which is to set the mask to "00:00". It brings up a separate issue, but solves the problem here.