Reputation: 1347
I have 3 columns (orderType, po number, bill id) that I am grouping by and I am using formatDisplayField to add a link/button to each group text so when clicked will open a context menu that will allow my users to add subgroups to that group. I need to pass the immediate row data that pertains to that group. Right now I am doing something sort of hacky and the data isnt specific enough.
Example:
A user clicks on the group ordertype
and gets a context menu that says Add PO Number
, they can then add a po number and on that group header they get a context menu that says Add Billing Id
. User can also add a billing id without adding a po number, this is important because this is where my data gets wonky. Lets say grid looks like:
OrderGroupType: Direct
PONumber: 12345
BillingId: abc
OrderGroupType: Direct
BillingId: abc
I can't seem to figure out how to get the data rows that have to do with the current group so I get all the data from the grid and then search through it and only return rows that equal my group name and then I put that information into a data attribute where I pull the information out in the context menu:
groupText: ['Group Type: <b>{0} - {1} Item(s)</b>',
'PO Number: <b>{0} - {1} Item(s)</b>',
'Bill To: <b>{0} - {1} Item(s)</b>'
],
formatDisplayField: [
function (ordgrpTypVal) {
//all rowData
var allRowData = $(this).jqGrid("getGridParam", "data");
//this row data
var rowData = $.grep(allRowData, function (v) {
return v.OrderGroupType == grpTypVal;
});
var elementId = "groupType_" + grpTypVal.replace(/\s+/g, '') + "_" + i++;
var newElement = '<span id="' + elementId + '" data-rowdata=\'' + JSON.stringify(rowData).replace(/'/g, "\\'") +'\' class="groupTypeMenu" style="cursor: pointer; color: blue;">' + grpTypVal + '</span>';
return newElement;
}
]
Where I am going wrong is I then have two more functions in that formatDisplayField
property where I also set links/button onto the child groups:
formatDisplayField: [
function (grpTypVal) {
//all rowData
var allRowData = $(this).jqGrid("getGridParam", "data");
//this row data
var rowData = $.grep(allRowData, function (v) {
return v.OrderGroupType == grpTypVal;
});
var elementId = "groupType_" + grpTypVal.replace(/\s+/g, '') + "_" + i++;
var newElement = '<span id="' + elementId + '" data-rowdata=\'' + JSON.stringify(rowData).replace(/'/g, "\\'") +'\' class="groupTypeMenu" style="cursor: pointer; color: blue;">' + grpTypVal + '</span>';
return newElement;
},
function (poVal) {
if (poVal !== null) {
//all rowData
var allRowData = $(this).jqGrid("getGridParam", "data");
//this row data
var rowData = $.grep(allRowData, function (v) {
return v.PoNumber == poVal;
});
var elementId = "PoNum_" + poVal.replace(/\s+/g, '') + "_" + i++;
var newElement = '<span id="' + elementId + '" data-rowdata=\'' + JSON.stringify(rowData).replace(/'/g, "\\'") + '\' class="poMenu" style="cursor: pointer; color: blue;">' + poVal + '</span>';
return newElement;
}
else
return null;
},
function (billToVal, val, props, index, obj) {
if (billToVal !== null) {
//all rowData
var allRowData = $(this).jqGrid("getGridParam", "data");
//this row data
var rowData = $.grep(allRowData, function (v) {
return v.BillToId == billToVal;
});
var elementId = "BillTo_" + billToVal.replace(/\s+/g, '') + "_" + i++;
var newElement = '<span id="' + elementId + '" data-rowdata=\'' + JSON.stringify(rowData).replace(/'/g, "\\'") + '\' class="billToMenu" style="cursor: pointer; color: blue;">' + billToVal + '</span>';
return newElement;
}
else
return null;
}
]
This breaks down when I have a billing id that has a parent po number with the same billing id. It could also break down if I had two po numbers that were exactly the same in two different order groups.
So my question is how can I get the data that pertains to the group more reliably? I'd prefer that I only get rowData that has to do with the specific group. I could see that happening if I could get more data, maybe something like:
formatDisplayField: [
function (billToVal, val, props, index, obj) {
if (billToVal !== null) {
//all rowData
var allRowData = $(this).jqGrid("getGridParam", "data");
//this row data
var rowData = $.grep(allRowData, function (v) {
return v.BillToId == billToVal **&& v.PoNumber == obj.PoNumber && v.OrderGroupType == obj.OrderGroupType;**
});
var elementId = "BillTo_" + billToVal.replace(/\s+/g, '') + "_" + i++;
var newElement = '<span id="' + elementId + '" data-rowdata=\'' + JSON.stringify(rowData).replace(/'/g, "\\'") + '\' class="billToMenu" style="cursor: pointer; color: blue;">' + billToVal + '</span>';
return newElement;
}
else
return null;
}
]
The fiddle below illustrates my issue; to see it working click MANUALS and choose edit, you will see it highlights the rows under manuals to orange, however, if you click on 1
under DSPO
and click edit, you will see it colors all the rows that have a billing id of 1
instead of just the row group you chose... The rows that are going to be edited should color orange.
JSFIDDLE
Any help would be phenomenal, I have tried lots of different things and the data is just not reliable. Thanks!
Upvotes: 0
Views: 550
Reputation: 222017
It seems to me that your code too complex as it could be. The first very important problem: your input data don't contain id
property with unique value. You place for example JSON.stringify(rowData)
instead of comma separated list of rowid
only because your input data has no id
value. If the value of RecurringOrderLineTemplateId
column for example is unique then you can add key: true
in the column and jqGrid will use the value as the rowid. If the composite key (RecurringOrderHeaderTemplateId
, RecurringOrderLineTemplateId
) is unique instead then you can fill id
property with the values item.RecurringOrderHeaderTemplateId + "_" + item.RecurringOrderLineTemplateId
. You will be able to get the values RecurringOrderHeaderTemplateId
and RecurringOrderLineTemplateId
from the rowid by usage rowid.split("_")
. Setting good rowid will not solve your main problem, but it will save your time later.
The main problem in your existing code seems to me the usage of $.grep
over the whole data inside of formatDisplayField
callback. It seems me wrong from performance point of view and from the common design. The data of the grid are already groupped, but you try redo the same once more inside of every formatDisplayField
call. I don't like it.
I'm not sure that I full understand what you try to implement. It seems to me that you set data-rowdata
on the <span>
element of the column header only to be able to use $link.data('rowdata')
later inside of click
handler of the context menu. You can add
var $tr = $(e.target).closest("tr.jqgroup"),
jqgrouplevel = parseInt($($tr).data("jqgrouplevel"), 10);
inside of build
callback of the contextMenu
and to use just
edit: {
...
callback: function () {
for ($tr = $tr.next(); $tr.length; $tr = $tr.next()) {
if ($tr.hasClass("jqgroup") && parseInt($tr.data("jqgrouplevel"), 10) <= jqgrouplevel) {
break; // stop enumeration
} else if ($tr.hasClass("jqgrow")) {
$tr.addClass("markedForModification"); // mark the row
}
}
//EditBillToHeader(rowData)
}
The modified demo https://jsfiddle.net/dv4v8mmz/3/ uses the above code with some additional alerts
in ".billToMenu" and in ".poMenu" (just duplicating the code). You can see that the approach works.
Upvotes: 1