Related
How could I disallow a cell in my kendo grid to be 'blank' or 'empty' rather... How could I replace all blank or empties with a 0..
I have a save button grabbing the values from my kendo grid such as below: Everything works fine EXCEPT, it is completely omitting my empty cells.. I want to keep them, just have a 0 value on them...
Save button: want to keep the empties with simply a 0 or N/A..
$('.' + chs).on('click', '#saveChanges', function(e) {
which = $(frm).attr("class");
let dataSource = $("#grid").data("kendoGrid").dataSource,
data = dataSource.data(),
changedModels = [];
if(dataSource.hasChanges) { // only saves cells/row that have been edited/changed, need to keep this
for(var i = 0; i < data.length; i++) {
if(data[i].dirty) { changedModels.push(data[i].toJSON()) }
}
}
let ds = JSON.stringify(changedModels);
$.ajax({
type: "POST",
url: "saveGrid",
dataType: "json",
data: {
id: which,
data: ds
},
success: function(result) {
console.log('yy');
},
error: function(result) {
console.log('nn');
}
});
});
This is my kendo grid initialized:
let dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "/popGrid?id=" + which,
dataType: "json"
},
},
batch: true,
schema: {
data: "data",
model: {
id: id,
}
},
});
console.log(id);
$("#grid").kendoGrid({
dataSource: dataSource,
height: 600,
sortable: true,
autoBind: true,
nullable: true,
editable: {
createAt: "top"
},
change: function(e) {
let grid = $("#grid").data("kendoGrid");
let selectedItem = grid.dataItem(grid.select());
let val = selectedItem.id;
console.log(val);
},
selectable: "row",
toolbar: [
{ name: "create" },
{ name: "cancel" }
],
paging: false,
});
I can't understand if you want to POST empty fields as "0" or if you want to SHOW them in the grid as "0", when null or "empty".
But I guess you're talking about posting it as "0". In that case I think you have to do that before posting:
let fieldName = 'myCell';
if (data[i].dirty) {
if (!data[i].hasOwnProperty(fieldName) || // In case field is not present on data
!data[i][fieldName]) { // In case field value is null/undefined/0/false/empty string
data[i][fieldName] = 0;
}
changedModels.push(data[i].toJSON());
}
For multiple field check:
let fieldNames = ['fieldA', 'fieldB', ...],
checkFields = (item) => {
fieldNames.forEach(field => {
if (!item.hasOwnProperty(field) || // In case field is not present on data
!item[field]) { // In case field value is null/undefined/0/false/empty string
item[field] = 0;
}
});
};
Or you can do the same before data is bound to the grid with dataSource.schema.parse.
I have a grid (made with jqGrid 4.15.2). The code looks like the one below:
$.jgrid = $.jgrid || {};
$.jgrid.no_legacy_api = true;
$.jgrid.useJSON = true;
$(function () {
"use strict";
var $grid = $("#list"),
maximizeGrid = function () {
var newWidth = $grid.closest(".ui-jqgrid").parent().width();
$grid.jqGrid("setGridWidth", newWidth, true);
};
// Resize grid if window is being resized
$(window).on("resize", maximizeGrid);
$grid.jqGrid({
colNames: ["", "Form #", "Form", "Plan", "Class", "Drug"],
colModel: [
{name: "act", template: "actions"},
{
name: "FormId",
align: 'center',
fixed: true,
frozen: true,
resizable: false,
width: 100,
editable: "hidden"
},
{name: "FormName", search: true, stype: "text"},
{name: "PlanName", search: true, stype: "text"},
{
name: "DrugGroupName",
edittype: "select",
editable: true,
search: true,
editoptions: {
dataUrl: "/ajax/drug_groups/get_all",
buildSelect: function (data) {
var select = "<select>", i;
for (i = 0; i < data.length; i++) {
select += "<option value='" + String(data[i].Id) + "'>" + $.jgrid.htmlEncode(data[i].DrugGroupName) + "</option>"
}
return select + "</select>";
},
selectFilled: function (options) {
setTimeout(function () {
$(options.elem).select2({
width: "100%"
});
}, 0);
}
},
stype: "select", searchoptions: {
sopt: ["eq", "ne"],
generateValue: true,
noFilterText: "Any",
selectFilled: function (options) {
setTimeout(function () {
$(options.elem).select2({
width: "100%"
});
}, 0);
}
}
},
{name: "DrugName", search: true, stype: "text"}
],
cmTemplate: {
width: 300,
autoResizable: true
},
iconSet: "fontAwesome",
rowNum: 25,
guiStyle: "bootstrap",
autoResizing: {
compact: true,
resetWidthOrg: true
},
rowList: [25, 50, 100, "10000:All"],
toolbar: [true, "top"],
viewrecords: true,
autoencode: true,
sortable: true,
pager: true,
toppager: true,
cloneToTop: true,
hoverrows: true,
multiselect: true,
multiPageSelection: true,
rownumbers: true,
sortname: "Id",
sortorder: "desc",
loadonce: true,
autowidth: true,
autoresizeOnLoad: true,
forceClientSorting: true,
prmNames: {id: "Id"},
jsonReader: {id: "Id"},
url: '/ajax/plans_to_forms/get_all',
datatype: "json",
editurl: '/ajax/plans_to_forms/update',
formDeleting: {
url: '/ajax/plans_to_forms/delete/',
delicon: [true, "left", "fa-scissors"],
cancelicon: [true, "left", "fa-times"],
width: 320,
caption: 'Delete Plan to Form Link',
msg: 'Are you sure you want to delete this link?',
beforeShowForm: function ($form) {
var rowids = $form.find("#DelData>td").data("rowids");
$form.closest(".ui-jqdialog").position({
of: window,
my: "center center",
at: "center center"
});
if (rowids.length > 1) {
$form.find("td.delmsg").html('Are you sure you want to delete all the selected form links?');
}
},
afterComplete: function (response, postdata, formid) {
if (response.responseText === "true") {
toastr["success"]("The link was deleted successfully.", "Information");
} else {
toastr["error"]("Something went wrong, the link could not be deleted.", "Error");
}
}
},
ajaxSelectOptions: {
type: "POST",
dataType: "json"
},
navOptions: {
edit: false,
add: false,
search: false
},
inlineEditing: {
keys: true,
focusField: "DrugGroupName",
serializeSaveData: function (postData) {
var changedData = {}, prop, p = $(this).jqGrid("getGridParam"),
idname = p.keyName || p.prmNames.id,
oldValue, cm;
for (prop in postData) {
oldValue = p.savedRow[0][prop];
if (p.iColByName[prop] != null) {
cm = p.colModel[p.iColByName[prop]];
}
if (postData.hasOwnProperty(prop) && (postData[prop] !== oldValue || prop === idname)) {
changedData[prop] = postData[prop];
}
}
return changedData;
},
aftersavefunc: function () {
toastr["success"]("The record was updated successfully.", "Information");
},
errorfunc: function () {
toastr["error"]("Something went wrong, the record could not be updated.", "Error");
}
},
onSelectRow: function (rowid, status, e) {
var $self = $(this),
$td = $(e.target).closest("tr.jqgrow>td"),
p = $self.jqGrid("getGridParam"),
savedRow = p.savedRow;
if (savedRow.length > 0 && savedRow[0].id !== rowid) {
$self.jqGrid("restoreRow", savedRow[0].id);
}
if ($td.length > 0 && $td[0].cellIndex !== p.iColByName.act) {
// don't start editing mode on click on "act" column
$self.jqGrid("editRow", rowid);
}
},
loadComplete: function () {
var $self = $(this), p = $self.jqGrid("getGridParam");
if (p.datatype === "json") {
// recreate the toolbar because we use generateValue: true option in the toolbar
$self.jqGrid("destroyFilterToolbar").jqGrid("filterToolbar");
}
}
}).jqGrid('navGrid').jqGrid("filterToolbar").jqGrid('setFrozenColumns');
// fill top toolbar
$('#t_' + $.jgrid.jqID($grid[0].id)).append($("<div><label for=\"globalSearchText\">Global search in grid for: </label><input id=\"globalSearchText\" type=\"text\"></input> <button id=\"globalSearch\" type=\"button\">Search</button></div>"));
$("#globalSearchText").keypress(function (e) {
var key = e.charCode || e.keyCode || 0;
if (key === $.ui.keyCode.ENTER) { // 13
$("#globalSearch").click();
}
});
$("#globalSearch").button({
icons: {primary: "ui-icon-search"},
text: false
}).click(function () {
var postData = $grid.jqGrid("getGridParam", "postData"),
colModel = $grid.jqGrid("getGridParam", "colModel"),
rules = [],
searchText = $("#globalSearchText").val(),
l = colModel.length,
i,
cm;
for (i = 0; i < l; i++) {
cm = colModel[i];
if (cm.search !== false && (cm.stype === undefined || cm.stype === "text")) {
rules.push({
field: cm.name,
op: "cn",
data: searchText
});
}
}
postData.filters = JSON.stringify({
groupOp: "OR",
rules: rules
});
$grid.jqGrid("setGridParam", {search: true});
$grid.trigger("reloadGrid", [{page: 1, current: true}]);
return false;
});
});
When I filter something and then want to mark the filtered results for delete all of them for some reason everything gets selected even those that hasn't been filtered which is sending all the IDs to the backend and therefore I am loosing everything when deleting based on the ID.
Maybe it's an stupid option or something else but I can't find what is wrong. Here is a video I have made showing up the issue. Here is a Fiddle for play with where you can see the issue happening
Steps to reproduce the issue:
Filter the column Filename by test
Using the first checkbox mark all of them
Without un-mark anything, remove the filter
Result: everything has been selected and therefore will be posted
Any ideas? Any help?
I find the problem, which you describe, very interesting and thus I changed the default behavior of "Select All" button (checkbox) to select only currently filtered data (see the commit). The new option selectAllMode with the value "all" allows to have the old behavior.
Your demo uses the latest free jqGrid directly from GitHub and thus it should work already like you want.
I am using the free jqGrid v4.12.1. (Can't post links to fiddle yet so code follows post)
The primary issue is that we are trying to do all searching/filtering with the filterToolbar. Oleg had helped a few weeks back push just dates to the search modal, but the requirement has changed to get a date range picker working in the filterToolbar. We are mostly there. Using Dan Grossman's bootstrap daterange picker and calling a custom function, it works like a charm.
Entering DateRangeFirst
The problem originally came in to play when you would select another value like an invoice amount. It would then override the date range and give all values "ge" to the start date. So it was seeing the beginning date of the string. To circumvent this, I called the invoiceDateSearch function again in beforeSearch. This way it ran the function again and recognized the start date and end dates along with the new value we are asking for.
The thing that happens now is that if I put any other value in first and then select a daterange, the daterange won't fire until I key some other search criteria and back it out.
AnyOther value first
It doesn't even recognize the date range was entered yet, when clearly it is there. triggerToolbar, reload grid is called in the function for the invoice date search.
When using beforeSearch, keeps the date range as a date range and not a string...regardless of how often the toolbar is triggered and values are backed out of any other fields, which is great. The downside to it is if a user puts a value other than the date range FIRST, the date range doesn't work...unless a subsequent field is entered. Not using it, converts the date range to a string after the first time it is used and any other values entered or filtered will require re-running the date parameters, because it gives every date greater than the start date.
I've put advanced search on the grid while troubleshooting. I'd like to take it off (or at least the buttons), as users want to just use the toolbarFilter.
My questions, how can I get the date range picker working in concert with the other column values? Is there an issue running two date pickers at once? The single date date picker just isn't responding at all when it's used. It will put the date there, and once another field is fired, it will respond, but never by itself.
Sorry if I "info dumped" I am fairly new at this. I've searched quite a bit for help to this and can't find much of anything. If I keep hacking at this, I am going to tear up what I have working! :O
Thanks in advance for any help or guidance!
$(function () {
"use strict";
var $grid = $("#vGrid2"),
lastSel;
function modifySearchingFilter(separator) {
var i,
l,
rules,
rule,
parts,
j,
group,
str,
filters = $.parseJSON(this.p.postData.filters);
if (filters && typeof filters.rules !== 'undefined' && filters.rules.length > 0) {
rules = filters.rules;
for (i = 0; i < rules.length; i++) {
rule = rules[i];
if (rule.op === 'cn') {
// make modifications only for the 'contains' operation
parts = rule.data.split(separator);
if (parts.length > 1) {
if (typeof filters.groups === 'undefined') {
filters.groups = [];
}
group = {
groupOp: 'AND',
groups: [],
rules: []
};
filters.groups.push(group);
for (j = 0, l = parts.length; j < l; j++) {
str = parts[j];
if (str) {
// skip empty '', which exist in case of two separators of once
group.rules.push({
data: parts[j],
op: rule.op,
field: rule.field
});
}
}
rules.splice(i, 1);
i--; // to skip i++
}
}
}
this.p.postData.filters = JSON.stringify(filters);
}
};
//TODO: search is filtering in the grid but only from start date and either ge or le start date based on which is first in the column
//TODO: (cont)model. Need to see why end date is not picking up from function.
function invoiceDateSearch($subGrid) {
var postData = $subGrid.getGridParam("postData");
// If there is no post data for some reason, get outta here
if (!postData) {
return;
}
// Make sure the filters object is constructed
var field = "InvoiceDate";
if (!postData.filters) {
postData.filters = {
groupOp: "AND",
rules: []
}
} else {
postData.filters = jQuery.jgrid.parse(postData.filters);
// Need to clear out existing invoice date rules
for (var i = postData.filters.rules.length - 1; i >= 0; i--) {
if (postData.filters.rules[i].field === field) {
postData.filters.rules.splice(i, 1);
}
}
}
var dateRangeString = $("#gs_InvoiceDate").val();
if (dateRangeString.length > 0) {
var dateRange = dateRangeString.split("-");
var startDate = dateRange[0];
var endDate;
if (dateRange.length == 1) {
endDate = dateRange[0];
} else {
endDate = dateRange[1];
}
postData.filters.rules.push({ "field": field, "op": "ge", "data": startDate.trim() });
postData.filters.rules.push({ "field": field, "op": "le", "data": endDate.trim() });
postData.filters = JSON.stringify(postData.filters);
// Need to set the grid's search to true, not the postData's
$subGrid.setGridParam({ search: true });
$subGrid.trigger("reloadGrid", [{ current: true, page: 1 }]);
}
}
function paymentDateSearch($subGrid) {
var postData = $subGrid.getGridParam("postData");
// If there is no post data for some reason, get outta here
if (!postData) {
return;
}
// Make sure the filters object is constructed
var field = "PaymentDate";
if (!postData.filters) {
postData.filters = {
rules: []
}
} else {
postData.filters = jQuery.jgrid.parse(postData.filters);
// Need to clear out existing invoice date rules
for (var i = postData.filters.rules.length - 1; i >= 0; i--) {
if (postData.filters.rules[i].field === field) {
postData.filters.rules.splice(i, 1);
}
}
}
var dateString = $("#gs_PaymentDate").val();
if (dateString.length > 0) {
var startDate = dateRange[0];
postData.filters.rules.push({ "field": field, "op": "eq", "data": startDate.trim() });
postData.filters = JSON.stringify(postData.filters);
// Need to set the grid's search to true, not the postData's
$subGrid.setGridParam({ search: true });
$subGrid.trigger("reloadGrid", [{ current: true, page: 1 }]);
}
}
//**TO overwrite jquery.ui icons and use fontAwesome. extending allows for customization of fA icons set as default in grid**//
$.extend(true, $.jgrid.icons.fontAwesome, {
common: "fa",
sort: {
common: "fa-sort fa-lg"
//asc: "fa-sort",
//desc: "fa-sort"
},
nav: {
common: "fa",
refresh: "fa-recycle fa-lg"
}
});
//**TOOLTIP ADD ON**//
$("[title]").qtip({
position: {
my: "bottom center",
at: "top center",
viewport: $(window)
}
});
//**PRIMARY GRID**//
$grid.jqGrid({
url: "VendInvoice/Vendor",
datatype: "local",
data: gridData,
colNames: ["ID", "Vendor Number", "Vendor Name", "dba", "VendorDbaCombo"],
colModel: [
{ key: true, name: "ID", width: 0, hidden: true, sortable: false, search: false },
{
key: false,
title: false,
name: "VendorNo",
index: "VendorNo",
width: 100,
sortable: true,
search: true,
stype: "text",
searchoptions: {
sopt: ["cn"],
attr: { title: "Enter all or part of a Vendor Number." },
clearSearch: false
}
},
{
key: false,
title: false,
name: "VendorName",
//index: "VendorName",
width: 500,
sortable: true,
search: true,
clearSearch: false,
stype: "text",
searchoptions: {
sopt: ["cn"],
clearSearch: false, //removes X in column filters
attr: {
title: "Enter a Vendor Name. SEARCHTIP: Once you start typing, you will begin returning filtered data. To broaden results returned provide less information, to narrow results provide more.",
maxlength: 9080,
dataInit: function (elem) {
$(elem).width(600);
}
}
}
},
{
key: false,
title: false,
name: "Dba",
index: "Dba",
width: 500,
sortable: true,
search: true,
stype: "text",
searchoptions: {
sopt: ["cn"],
attr: { title: "Enter all or part of a dba." },
clearSearch: false
}
},
{ key: false, name: "VendorDbaCombo", index: "VendorDbaCombo", width: 1, hidden: true }
],
//**PRIMARY GRID PROPERTIES**//
cmTemplate: { autoResizable: true, editable: true },
iconSet: "fontAwesome",
hidegrid: false,
forceFit: true,
caption: "Vendor Results",
ignoreCase: true,
gridview: true,
autoencode: true,
pager: "#Pager",
toppager: true,
rowNum: 25,
rowList: [5, 10, 25],
autowidth: true,
height: "auto",
viewrecords: true,
loadonce: true,
sortName: "VendorName",
sortOrder: "ASC",
viewsortcols: [true, "vertical", true],
forceClientSorting: true,
multiselect: true,
setGridWidth: 980,
loadtext: "Fetching your data, back in a jiff!",
emptyrecords: "There were no records, try narrowing your search criteria",
loadComplete: function () {
$(this).find(">tbody>tr.jqgrow:visible:odd").addClass("myAltRowClass");
},
onSelectRow: function (row_id) {
$grid.jqGrid("toggleSubGridRow", row_id);
if (row_id !== lastSel && typeof lastSel !== "undefined") {
$grid.jqGrid("setRowData", row_id, false, "myNormal");
}
$grid.jqGrid("setRowData", row_id, false, "myBold");
lastSel = row_id;
},
//**SET SUBGRID**//
subGrid: true,
subGridOptions: {
plusicon: "fa fa-plus-square-o",
minusicon: "fa fa-minus-square-o",
reloadOnExpand: false,
expandOnLoad: false,
delayOnLoad: 50
},
jsonReader: {
id: "id",
root: "rows",
total: "total",
records: "records",
subgrid: {
root: "rows",
repeatitems: true, //must be true in subgrid and false in main grid
cell: ""
}
},
subGridRowExpanded: function (subgrid_id, row_id) {
var subgrid_table_id, pager_id;
subgrid_table_id = subgrid_id + "_t";
var selectedrow = $(this).jqGrid('getRowData', row_id);
pager_id = "p_" + subgrid_table_id;
var stat = function (subgrid_id, row_id) {
$("#vGrid2").jqGrid("setSelection", "row_id"); //Test to set selection for toggle
}
//**SUBGRID**//
$("#" + subgrid_id).html("<table id='" + subgrid_table_id + "'class='scroll'></table><div id='" + pager_id + "'class='scroll'></div>");
$("#" + subgrid_table_id).jqGrid({
url: "VendInvoice/VendInvoiceSubGridData?vendorID=" + row_id,
datatype: "local",
data: subgridData[rowId],
postData: {
vendorID: row_id,
},
colNames: ["vendorID", "Invoice Status", "Invoice No", "Invoice Date", "Invoice Amount($)", "Payment Date", "Check or ACH Number", "Check or ACH Amount($)", "Encashment Date"],
colModel: [
{ name: "vendorID", key: true, index: "vendorID", hidden: true, width: 0 },
{
name: "InvoiceStatus",
title: false,
index: "InvoiceStatus",
width: 140,
sortable: true,
search: true,
formatter: "select",
stype: "select",
searchoptions: {
sopt: ["cn"],
attr: { title: "If part of your search criteria, select an invoice status from the drop-down menu." },
value: ":Select (All);Paid:Paid;Processing for Payment:Processing for Payment;Reviewing:Reviewing"
}
},
{
name: "InvoiceNo",
title: false,
index: "InvoiceNo",
width: 125,
sortable: true,
search: true,
stype: "text",
searchoptions: {
sopt: ["cn", "eq"],
attr: { title: "Enter all or part of an invoice number." },
clearSearch: false
}
},
{
name: "InvoiceDate",
title: false,
index: "InvoiceDate",
width: 135,
formatter: "date",
formatoptions: { srcformat: "m/d/Y", newformat: "m/d/Y" },
jsonmap: function (obj) {
var d = new Date(parseInt(obj.matchstartDate, 10));
return d.getFullYear() + "/" + (d.getMonth() + 1) + "/" + d.getDate()
},
sortable: true,
sorttype: "date",
editable: true,
search: true,
stype: "text",
searchoptions: {
sopt: ["ge", "le"],
clearSearch: false,
attr: { title: "Click in the box to open the date range picker." },
dataInit: function (elem) {
$(elem).daterangepicker({
dateFormat: 'mm/dd/yy',
changeYear: true,
changeMonth: true,
todayHighlight: true,
});
//ranges: {
// "Yesterday": [moment(), subtract(1, 'days'), moment().subtract(1, 'days')],
// "Last 7 days": [moment().subtract(6, 'days'), moment()],
// "Last Month": [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')],
// "This YTD": [moment().startOf('year'), moment().endOf('year')],
// "LastYear": [moment().subtract(1,'year').startOf('year'), moment.subtract(1,'year').endOf('year')]
// }
$(document).on('apply.daterangepicker', function () {
var $subGrid = $("#" + subgrid_table_id);
invoiceDateSearch($subGrid);
});
}
}
},
{
name: "InvoiceAmount",
title: false,
index: "InvoiceAmount",
width: 95,
sortable: true,
sorttype: "float",
formatter: "currency",
formatoptions: {
//prefix: "$",
suffix: "", thousandsSeparator: ",", decimalPlaces: 2
},
search: true,
stype: "text",
searchoptions: {
sopt: ["eq"],
attr: { title: "Enter an invoice amount." },
clearSearch: false
}
},
{
name: "PaymentDate",
title: false,
index: "PaymentDate",
width: 135,
formatter: "date",
formatoptions: { srcformat: "m/d/Y", newformat: "m/d/Y" },
jsonmap: function (obj) {
var d = new Date(parseInt(obj.matchstartDate, 10));
return d.getFullYear() + "/" + (d.getMonth() + 1) + "/" + d.getDate()
},
sortable: true,
sorttype: "date",
editable: true,
search: true,
stype: "text",
searchoptions: {
sopt: ["eq"],
clearSearch: false,
attr: { title: "Click in the box to open the date range picker." },
dataInit:
function (el) {
$(el).datepicker({
dateFormat: 'mm/dd/yy',
changeYear: true,
changeMonth: true,
todayHighlight: true,
orientation: "bottom",
immediateUpdates: true,
autoclose: true
}).on('changeDate', function () {
var $subGrid = $("#" + subgrid_table_id);
paymentDateSearch($subGrid);
$subGrid.setGridParam({ search: true });
$subGrid.trigger("reloadGrid", [{ current: true, page: 1 }]);
});
}
}
},
{
name: "PaymentNo",
title: false,
index: "PaymentNo",
width: 115,
sortable: true,
search: true,
stype: "text",
searchoptions: {
sopt: ["cn", "eq"],
attr: { title: "Enter all or part of a Check or ACH Number." },
clearSearch: false
}
},
{
name: "CheckAmount",
title: false,
index: "CheckAmount",
width: 95,
sortable: true,
sorttype: "float",
formatter: "currency",
formatoptions: { suffix: "", thousandsSeparator: ",", decimalPlaces: 2 },
search: true,
stype: "text",
searchoptions: {
sopt: ["eq"],
attr: { title: "Enter a payment amount." },
clearSearch: false
}
},
{
name: "EncashmentDate",
title: false,
index: "EncashmentDate",
width: 100,
sortable: true,
sorttype: "date",
formatter: "date",
formatoptions: { srcformat: "m/d/Y", newformat: "m/d/Y" },
search: false
}
],
//**SUBGRID PROPERTIES**//
cmTemplate: {
align: "center",
autoResizeable: true
},
idPrefix: "_s",
iconSet: "fontAwesome",
loadonce: true,
loadtext: "Grabbing those invoice, this may take a second!",
autoencode: true,
toppager: true,
autowidth: true,
sortable: true,
showOneSortIcon: true,
autoResizing: { widthOfVisiblePartOfSortIcon: 13 },
viewsortcols: [true, "vertical", true],
multiselect: true,
height: "auto",
rowNum: 500,
rowList: [25, 50, 100, 250, 500],
gridview: true,
viewrecords: true,
emptyrecords: "There were no records, try narrowing your search criteria",
prmNames: {
id: "vendorID"
},
pager: "#" + pager_id,
loadComplete: function () {
$(this).find(">tbody>tr.jqgrow:visible:odd").addClass("myAltRowClass2");
},
beforeSelectRow: function () {
return false;
}
});
jQuery("#" + subgrid_table_id).jqGrid("navGrid", "#" + pager_id, {
edit: false,
add: false,
del: false,
search: true,
refresh: true,
refreshtext: "Refresh Invoice Results",
cloneToTop: true
},
{},
{},
{},
{
multipleSearch: true,
});
jQuery("#" + subgrid_table_id).jqGrid("navButtonAdd", "#" + pager_id, {
caption: "Export to Excel",
buttonicon: "fa-file-excel-o",
onClickButton: function (e) {
exportData(e, "#" + subgrid_table_id);
},
position: "last"
});
jQuery("#" + subgrid_table_id).jqGrid("filterToolbar", {
stringResult: true,
searchOnEnter: false,
ignoreCase: true,
autoSearch: true,
autosearchDelay: 1000,
attr: {
style: "width: auto;padding:0;max-width:100%"
},
defaultSearch: "cn",
//beforeSearch: function () {
// var $subGrid = $("#" + subgrid_table_id);
// invoiceDateSearch($subGrid);
// $subGrid.trigger("reloadGrid", [{ current: true, page: 1 }]);
//}
});
$("[title]").qtip({
position: {
my: "bottom center",
at: "top center",
viewport: $(window)
}
});
var names = [
"Invoice Status", "Invoice No", "Invoice Date", "Invoice Amount", "Payment Date",
"Check or ACH No", "Check or ACH Amount", "Encashment Date"
];
var mydata = [];
var i, j;
if (mydata != null) {
for (i = 0; i < mydata.length; i++) {
mydata[i] = {};
for (j = 0; j < mydata[i].length; j++) {
mydata[i][names[j]] = mydata[i][j];
}
}
}
for (var i = 0; i <= mydata.length; i++);
$("#" + subgrid_table_id).jqGrid('addRowData', i + 1, mydata[i]);
}
}).jqGrid("navGrid", "#Pager", {
edit: false,
add: false,
del: false,
search: false,
refresh: true,
refreshtext: "Refresh Results",
cloneToTop: true
}).jqGrid("filterToolbar", {
stringResult: true,
searchOnEnter: false,
ignoreCase: true,
autoSearch: true,
autosearchDelay: 1000,
attr: {
style: "width: auto;padding:0;max-width:100%"
},
defaultSearch: "cn",
beforeSearch: function () {
modifySearchingFilter.call(this, " ");
}
}).jqGrid("gridResize");
//**TOOLTIP ADD ON**//
$("[title]").qtip({
position: {
my: "bottom center",
at: "top center",
viewport: $(window)
}
});
//**HIDE 'SELECT ALL' CHECKBOX** call after grid is loaded//
$("#cb_" + $grid[0].id).hide();
$("#vGrid2").jqGrid("hideCol", "subgrid");
//**CUSTOM TOOLTIP TEXT FOR COLUMN HEADERS IN PRIMARY GRID**//
var setTooltipsGrid = function (grid, iColumn, text) {
var thd = jQuery("thead:first", grid[0].grid.hDiv)[0];
jQuery("tr.ui-jqgrid-labels th:eq(" + iColumn + ")", thd).attr("title", text);
};
$(".hasTooltip").each(function () {
$(this).qtip({
content: {
text: $(this).next("div")
}
});
});
//setTooltipsGrid($("#vGrid2"), 0, "If exporting, ensure ONLY the row you wish to export is selected. Remove any unnecessary checks in this column.");
//**EXPORT TO EXCEL-CSV**//
function exportData(e, row_id) {
var subGrid = jQuery(row_id).getDataIDs(); // Get all the ids in array
var label = jQuery(row_id).getRowData(subGrid[0]); // Get First row to get the labels
var selRowIds = jQuery(row_id).jqGrid('getGridParam', 'selarrrow');
var obj = new Object();
obj.count = selRowIds.length;
if (obj.count) {
obj.items = new Array();
var elem;
for (elem in selRowIds) {
if (selRowIds.hasOwnProperty(elem)) {
obj.items.push(jQuery(row_id).getRowData(selRowIds[elem]));
}
}
var json = JSON.stringify(obj);
JSONToCSVConvertor(json, "csv", 1);
}
}
function JSONToCSVConvertor(JSONData, ReportTitle, ShowLabel) {
//If JSONData is not an object then JSON.parse will parse the JSON string in an Object
var arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData;
var CSV = '';
//This condition will generate the Label/Header
if (ShowLabel) {
var row = "";
//This loop will extract the label from 1st index of on array
for (var index in arrData.items[0]) {
//Now convert each value to string and comma-seprated
row += index + ',';
}
row = row.slice(0, -1);
//append Label row with line break
CSV += row + '\r\n';
}
//1st loop is to extract each row
for (var i = 0; i < arrData.items.length; i++) {
var row = "";
//2nd loop will extract each column and convert it in string comma-seprated
for (var index in arrData.items[i]) {
row += '"' + arrData.items[i][index].replace(/(<([^>]+)>)/ig, '') + '",';
}
row.slice(0, row.length - 1);
//add a line break after each row
CSV += row + '\r\n';
}
if (CSV == '') {
alert("Invalid data");
return;
}
//*** FORCE DOWNLOAD ***//
//will generate a temp "a" tag
var link = document.createElement("a");
link.id = "lnkDwnldLnk";
//this part will append the anchor tag and remove it after automatic click
document.body.appendChild(link);
var csv = CSV;
var blob = new Blob([csv], { type: 'text/csv' });
var myURL = window.URL || window.webkitURL;
var csvUrl = myURL.createObjectURL(blob);
var filename = 'UserExport.csv';
jQuery("#lnkDwnldLnk")
.attr({
'download': filename,
'href': csvUrl
});
jQuery('#lnkDwnldLnk')[0].click();
document.body.removeChild(link);
}
});
It seems to me that the usage of custom operation is the best approach to solve your problem. Of cause you can use beforeSearch callback of filterToolbar to modify the filter, but it's too low level operation and it will not work in Searching Dialog.
I would recommend you to read the wiki article which describes the feature. It provides an example with "numeric IN" operation, which you can easy modify to your requirements. The filter callback get in options all the information which you need and the callback should just verify that the data of the testing item (options.item) are inside of interval provided by the value from the date range picker (options.searchValue). I think that you will get small code, which solves your problem, in the way.
Final remark: I'd recommend you to upgrade to the latest 4.13.0 version which fix some bugs, improves performance in some cases and provides new features described in the readme.
The search button works on the first click, but once it is closed either by clicking the X (close button) or by running a search (setting to close after search) it does not open, there are also no errors in the console so I am unable to determine what is wrong and how to fix it.
var previouslySelectedRow = null;
var rowIsSelected = null;
var previousRowIsSelected = null;
var currentRowId;
var currentCount;
var cancelEditing = function(theGrid) {
var lrid;
if (typeof previouslySelectedRow !== "undefined") {
// cancel editing of the previous selected row if it was in editing state.
// jqGrid hold intern savedRow array inside of jqGrid object,
// so it is safe to call restoreRow method with any id parameter
// if jqGrid not in editing state
theGrid.jqGrid('restoreRow', previouslySelectedRow);
// now we need to restore the icons in the formatter:"actions"
lrid = $.jgrid.jqID(previouslySelectedRow);
$("tr#" + lrid + " div.ui-inline-edit").show();
$("tr#" + lrid + " div.ui-inline-save, " + "tr#" + lrid + " div.ui-inline-cancel").hide();
}
};
var parsedResult = JSON.parse(DecodeAscii(result));
ShowDebugNotification("DEBUG INFO(" + ajaxCall + "): <br />" + result, false);
$("#productsTable").jqGrid({
data: parsedResult,
datatype: "local",
loadonce: true,
height: 'auto',
marginLeft: 'auto',
colNames: [
'Product Id', 'Add', 'Product Name', 'Product Code', 'Customer Price'
],
colModel: [
{ name: 'Id', width: 0, hidden:true },
{ name: "actions", template: "actions", width: 50, formatoptions:{
delbutton: false,
editbutton: false
} },
{ name: 'Name', index: 'Name', width: 550, search: true, searchoptions:{sopt:['eq','bw','bn','cn','nc','ew','en']} },
{ name: 'ProductCode', index: 'ProductCode', width: 150, search: true, searchoptions:{sopt:['eq','bw','bn','cn','nc','ew','en']} },
{ name: 'Price', index: 'Price', width: 100, search: false, formatter: 'currency', formatoptions:{decimalSeparator:".", thousandsSeparator: ",", decimalPlaces: 2, prefix: "$"}}
],
rowNum: 15,
rowList: [5, 10, 15, 20],
pager: true,
gridView: true,
viewrecords: true,
iconSet: "jQueryUI",
sortname: 'Name',
sortorder: 'asc',
inlineEditing: { keys: false },
actionsNavOptions: {
addToCarticon: "ui-icon-cart",
addToCarttitle: "Add item to the cart",
custom: [
{ action: "addToCart", position: "first", onClick: function (options) {
var rowData = $('#productsTable').getRowData(options.rowid);
var cartButton = $(".ui-icon", "#jAddToCartButton_"+options.rowid);
if(cartButton.hasClass("ui-icon-cancel")){
cart.shift(rowData);
cartButton.removeClass("ui-icon-cancel");
cartButton.addClass("ui-icon-cart");
}
else if(cartButton.hasClass("ui-icon-cart")){
cart.push(rowData);
cartButton.removeClass("ui-icon-cart");
cartButton.addClass("ui-icon-cancel");
}
}
}]
},
loadComplete: function() {
$("#add-product-dialog-loading-message").hide();
$(".spinner").hide();
$("#add-product-dialog-form").dialog("open");
//for each object in cart
//if prodcut ID matches product Id in product
//grid then set button to a cancel icon
if(cart.length !== 0){
var cartIds = [];
var jsonCart = JSON.stringify(cart);
var parsedJsonCart = JSON.parse(jsonCart);
var productsInCart = $.grep(parsedJsonCart, function(el, i){
cartIds.push(el.Id);
});
var currentRows = $('#productsTable').getRowData();
var shownProductsThatAreInCart = $.grep(currentRows, function (el, i) {
return $.inArray(el.Id, cartIds) !== -1;
});
if(shownProductsThatAreInCart.length > 0){
var rowIds = $(this).jqGrid('getDataIDs');
$.each(rowIds, function(k, v) {
rowData = $('#productsTable').getRowData(v);
if($.inArray(rowData['Id'], cartIds) !== -1){
alert("Matched Product:\nRowData['id'] = " + rowData['Id'] + "\nto\nProduct in cart: " + cartIds.Id);
$(".ui-icon", "#jAddToCartButton_"+v).removeClass("ui-icon-cart");
$(".ui-icon", "#jAddToCartButton_"+v).addClass("ui-icon-cancel");
}
});
}
}
},
gridComplete: function() {
}
});
$("#productsTable").jqGrid("navGrid", {edit:false,add:false,del:false},
{},// use default settings for edit
{},// use default settings for add
{},// delete instead that del:false we need this
{multipleSearch:false,overlay:false,ignoreCase:true,closeAfterSearch:true,closeOnEscape:true,showQuery:true});
I don't think its a bug as I have seen many demos demonstrating how it is supposed to work, I am guessing I have a mis-configuration, please have a look over my code and help determine the issue.
One thing to keep in mind is I am getting the data to load the grid via an ajax call that returns json, all manipulation is done on the client, there is no posting data back to server at all.
Thank you!
The main problem is the combination of Searching options which you use:
{
multipleSearch: false, // it's default and can be removed
overlay: false, // !!! the option make the problem
ignoreCase: true, // it's not exist at all
closeAfterSearch: true,
closeOnEscape: true,
showQuery: true
}
The usage of the option overlay: false is bad because it makes another option toTop: true not working and the Searching dialog will be placed as the children of jQuery UI Dialog. If you remove the option then one can work with the Searching Dialog more easy and the second problem (a bug in calculation of position of jqGrid Searching Dialog) will not exist. Look at the modified demo:
https://jsfiddle.net/OlegKi/su7mf5k9/3/
UPDATED: It seems one have the problem in creating modal jqGrid dialog inside of modal jQuery UI dialog. The problem could be solved by removing modal: true option from the outer jQuery UI dialog. See https://jsfiddle.net/OlegKi/su7mf5k9/3/
In general one could create hybrid solution which changes the type of jQuery UI dialog from modal to non-modal dynamically, but it could be tricky https://jsfiddle.net/OlegKi/su7mf5k9/5/
i am using jqGrid with CodeIgniter 2.1.0 .
The thing which is making me harassed is how to assign value to specific column on specific event
Suppose i am entering qty and rate in column value.....and when i loss focus from "rate" field.....the net amount should be calculated and displayed in amount field...
what i need to do here is to assign calculated value to amount field......but i am not getting any idea regarding how do i do it??
what i have done is given below :
var selIRow = 1;
var rowid='';
var iCol='';
$("#purchasedetailsgrid").jqGrid({
url: sitepath + 'purchase/purchase_grid',
datatype: 'json',
mtype: 'POST',
height:220,
width:500,
colNames:["","","Store Name","Item Name","Inner Pkg.","Outer Pkg.","Qty","Rate","Amount"],
colModel:[
{name: 'storeID_hidden_field', index:'storeID_hidden_field',hidden: true, editable: true,edittype: 'text',editrules: {edithidden:true}},
{name: 'itemID_hidden_field', index:'itemID_hidden_field',hidden: true, editable: true,edittype: 'text',editrules: {edithidden:true}},
{name:'store_id', index:'store_id',width:150,search:false,editable:true,editrules:{number:false,maxlength:10}},
{name:'item_id', index:'item_id',width:150,search:false,editable:true,editrules:{number:false,maxlength:10}},
{name:'inner_pkg', index:'inner_pkg',width:150,search:false,editable:true,editrules:{number:true,maxlength:5}},
{name:'outer_pkg', index:'outer_pkg',width:150,search:false,editable:true,editrules:{number:true,maxlength:5}},
{name:'qty', index:'qty',editable:true,width:85,search:false,editrules:{number:true,maxlength:5}},
{name:'rate', index:'rate',width:100,editable:true,search:false,editrules:{number:true,maxlength:10},
editoptions: {
dataInit: function (elem) { $(elem).focus(function () { this.select(); }) },
dataEvents: [
{
type: 'keydown',
fn: function (e) {
var key = e.charCode || e.keyCode;
if (key == 9)//tab
{
$('#amount').val();//here in val() i need to write the value of qty and rate field
}
}
}
]
}
},
{name:'amount', index:'amount',width:100,editable:true,search:false,editrules:{number:true,maxlength:10},
editoptions: {
dataInit: function (elem) { $(elem).focus(function () { this.select(); }) },
dataEvents: [
{
type: 'keydown',
fn: function (e) {
var key = e.charCode || e.keyCode;
if (key == 13)//enter
{
var grid = $('#purchasedetailsgrid');
//Save editing for current row
grid.jqGrid('saveRow', selIRow, false, sitepath + 'purchase/purchase_grid');
selIRow++;
//If at bottom of grid, create new row
//if (selIRow++ == grid.getDataIDs().length) {
grid.addRowData(selIRow, {});
//}
//Enter edit row for next row in grid
grid.jqGrid('editRow', selIRow, false, sitepath + 'purchase/purchase_grid');
}
}
}
]
}
}
],
pager: '#purchasedetailstoolbar',
rowNum:10,
rowList:[10,20,30],
sortname: 'inventory_id',
sortorder: 'desc',
viewrecords: true,
rownumbers: true,
gridview: true,
multiselect: false,
autoresize:true,
autowidth: true,
editurl: sitepath + 'purchase/purchase_grid',
toolbar: [true,"top"],
gridComplete: function ()
{
var grid = jQuery("#purchasedetailsgrid");
var ids = grid.jqGrid('getDataIDs');
if(ids == '')
{
grid.addRowData(selIRow, {});
grid.jqGrid('editRow', selIRow, false, sitepath + 'purchase/purchase_grid');
}
for (var i = 0; i < ids.length; i++)
{
}
},
caption: 'Purchase List',
});
jQuery("#purchasedetailsgrid").jqGrid('navGrid','#purchasedetailstoolbar',{view:false,edit:false,add:false,del:false,search: false});
jQuery("#purchasedetailsgrid").jqGrid('inlineNav','#purchasedetailstoolbar');
jQuery("#purchasedetailsgrid").jqGrid('filterToolbar',{stringResult:false,searchOnEnter : false},{autosearch: true});
var temp_purchase = $("#purchasedetailsgrid_header").html();
$("#t_purchasedetailsgrid").html(temp_purchase);
$("#refresh_purchasedetailsgrid").attr('title',"Reload Grid");
Now can anyone suggest me how will i get value from one column and assign it another?
Any suggestions will be appreciated.
Thnx in advance
You current code have many problems. For example you wrote that you need that amount will be calculated based on qty and rate, but you defined some dataEvents in 'rate' and 'amount' columns instead of 'qty' and 'rate' columns. The next problem that you use editRow method directly inside of gridComplete. So the buttons from the inlineNav toolbar will stay in the wrong status. One more problem is that you need to recompute the 'amount' based on 'qty' and 'rate' not only on the loss of focus from 'qty' and 'rate', but also on saving the values on Enter.
To make solving of above problems easier I wrote the demo which you can modify corresponds your exact requirements. The most important part of the demo you can find below:
var editingRowId = undefined,
recomputeAmount = function () {
var rate = $("#" + editingRowId + "_rate").val(),
qty = $("#" + editingRowId + "_qty").val(),
newAmount = parseFloat(rate) * parseFloat(qty);
$("#" + editingRowId + "_amount").val(isFinite(newAmount) ? newAmount : 0);
},
myEditParam = {
keys: true,
oneditfunc: function (id) {
editingRowId = id;
},
afterrestorefunc: function (id) {
editingRowId = undefined;
},
aftersavefunc: function (id) {
var $this = $(this),
rate = $this.jqGrid("getCell", id, "rate"),
qty = $this.jqGrid("getCell", id, "qty"),
newAmount = parseFloat(rate) * parseFloat(qty);
$this.jqGrid("setCell", id, "amount", newAmount);
editingRowId = undefined;
}
},
numInput = {
type: 'keydown',
fn: function (e) {
var key = e.which;
// allow only '0' <= key <= '9' or key = '.', Enter, Tab, Esc
if ((key < 48 || key > 57) && key !== $.ui.keyCode.PERIOD &&
key !== $.ui.keyCode.TAB && key !== $.ui.keyCode.ENTER && key !== $.ui.keyCode.ESCAPE) {
return false;
}
}
},
recompute = {
type: 'focusout',
fn: function (e) {
recomputeAmount();
}
};
$("#purchasedetailsgrid").jqGrid({
colModel: [
...
{name:'qty', index:'qty',editable:true,width:85,search:false,editrules:{number:true,maxlength:5},
editoptions: {
dataInit: function (elem) { $(elem).focus(function () { this.select(); }) },
dataEvents: [ numInput, recompute ]
}
},
{name:'rate', index:'rate',width:100,editable:true,search:false,editrules:{number:true,maxlength:10},
editoptions: {
dataInit: function (elem) { $(elem).focus(function () { this.select(); }) },
dataEvents: [ numInput, recompute ]
}
},
{name:'amount', index:'amount',width:100,editable:true,search:false,editrules:{number:true,maxlength:10}}
],
loadComplete: function () {
var gridIdSelector = '#' + $.jgrid.jqID(this.id);
if (this.rows.length > 1) {
//$(this).jqGrid('editRow', this.rows[1].id, myEditParam);
$(this).jqGrid('setSelection', this.rows[1].id, true);
setTimeout(function() {
// we should simulate click of the button not after the grid is loaded, but
// after the toolbar with the cliked button will be created by inlineNav
$(gridIdSelector + "_iledit").click();
}, 100);
} else {
setTimeout(function() {
// we should simulate click of the button not after the grid is loaded, but
// after the toolbar with the cliked button will be created by inlineNav
$(gridIdSelector + "_iladd").click();
}, 100);
}
}
});
jQuery("#purchasedetailsgrid").jqGrid('navGrid','#purchasedetailstoolbar',
{view:false,edit:false,add:false,del:false,search: false, refreshtitle: "Reload Grid"});
jQuery("#purchasedetailsgrid").jqGrid('inlineNav','#purchasedetailstoolbar',
{edit: true, add: true, editParams: myEditParam, addParams: {addRowParams: myEditParam}});
If it's needed I can comment unclear parts of the code.