jqGrid: is it possible to selectively make cells editable? - jqgrid

how can I make one single cell editable out of a not editable column?
my javaScript looks like this:
$( '#grid' ).jqGrid({
// ...
cellEdit : true,
colModel : [
{ name : "id", index : "id", editable : false },
{ name : "wbs", index : "wbs", editable : false },
{ name : "value", index : "value", editable : false }
],
loadComplete : function(data) {
// ... foreach ( cell in data.rows.columns ) ...
if ( cell.shouldBeEditable ) {
jQuery('#grid').setCell(cell.row, cell.col, '', 'green', { editable : true });
}
}
// ...
}
so, after globally setting columns as not editable, I try to set them as editable locally, based on some criteria (to identify them more easily I also paint them green).
Alas, it's not working: cells become green, but when I try to click them they do not become editable.
Inspecting the selected cell with firebug reveals the edit-cell class to be correctly applied.
As a last note, it's working if I set columns as editable in the first instance.

I suggest you do it in reverse. Make the column editable, but disable the cells that you do not want to be editable. This is a function I wrote to disable cells:
// cellName is the name defined in your colModel
function disableGridCell(cellName) {
var cell = $('[name="' + cellName + '"]');
cell.css('display', 'none');
var div = $("<div>")
.css('width', '100%')
.css('height', '100%')
.css('border', '1px solid #000')
.css('background-color', '#CCC')
.text('xxxxxxxxxxxx');
cell.parent().append(div);
}
I call disableGridCell inside of my onEditFunc of my grid's editRow function:
$('#grid').jqGrid('editRow', id, keys, onEditFunc);
function onEditFunc(id) {
if (condition to disable cell) {
disableGridCell('CellName');
}
}

I found a nice workaround to the problem (thanks to Walter for getting me on the right track).
Instead of locking all the cells and selectively unlocking them in a declarative manner (which may lead to long load times), I'm declaring all the cells as editable.
Then I'm attaching a callback to afterEditCell option:
var $grid = $('#grid');
$grid.jqGrid({
// ...
afterEditCell : function(rowid, cellname, value, iRow, iCol) {
if ( shouldNotBeEditable(iRow, iCol) ) {
$grid.setCell(rowid, cellname, '', 'not-editable-cell');
$grid.restoreCell(iRow, iCol);
}
},
// ...
});
This way the cell is immediately reset to its previous value and I ensure that the callback gets called only once per not-to-be-edited cell, since the cell is made into a not-editable-cell after the first call.

colModel:[
{name:'description',index:'description', width:4, sortable: false, editable: true},
{name:'qty',index:'qty', width:1,sortable: false, editable: true},
{name:'cost',index:'cost', width:1, editable: true, sortable: false},
{name:'totalCost',index:'totalCost', width:1, sortable: false}
onCellSelect: function(rowid, iCol, cellcontent, e) {
//here it will allow editing of either qty or cost col for that rowid
//only if both cols have a numeric value already
if(iCol===1 || iCol===2) {
var rowdata = $("#projectTable").getRowData(rowid);
var itemCost = parseInt(rowdata['cost']);
var qty = parseInt(rowdata['qty']);
if(!$.isNumeric(itemCost) || !$.isNumeric(qty)) {
$("#projectTable").jqGrid('setColProp','qty',{editable: false});
$("#projectTable").jqGrid('setColProp','cost',{editable: false});
} else {
$("#projectTable").jqGrid('setColProp','qty',{editable: true});
$("#projectTable").jqGrid('setColProp','cost',{editable: true});
}
}
},

Related

How to prevent selecting a dropdown based on cell value condition in Jqgrid

i am trying to highlight the cells in Red whichever values not matching with my predefined values
and
1. i want to get the count of red cells in each row in the column Error_cells_Count,now in the demo page i have manually entered the count
2. and i want to prevent user from selecting the dropdown in status column if the row has any red cells.
i have managed to highlight the cells.
please help to get the red cells count in Error_cells_Count column and prevent user from selecting dropdown.
this is my demo page http://jsfiddle.net/h8Lzgh7d/27/
Jqgrid version version is 4.14.0
and also kindly suggest if any possibilities to have predefined dictionary and correct the red cells automatically by replacing the red cell values with dictionary value
First of all I'd recommend you to use cellattr to set any CSS properties on the cell. Seconds you can use editable defined as function to allow editing the cell depend on some your custom criteria (see the wiki article for more details).
The fixed demo could be the following https://jsfiddle.net/OlegKi/h8Lzgh7d/30/. It uses the following code:
var hilightcolorcell=["PURPLE","PINK","GREEN"];
var hilightcahractercell=["Character 1","Character 2","Character 3"];
jQuery("#rowed5").jqGrid({
datatype: "local",
shrinkToFit: false,
data: mydata,
height: 320,
autowidth:true,
colNames:['RowID','Error_Cells_Count','status','note','color_name','character_name','Variant ID'],
colModel: [
{name:'id', width:55, sorttype:"int",align:"center",frozen:true},
{name:'Error_Cells_Count', width:100, sorttype:"int",
align:"center",frozen:true,
cellattr: function (rowid, cellValue) {
if (cellValue != null) {
var value = parseInt(cellValue, 10);
return " class='" +
(value > 0 ? "redcells" : "greencells") +
"'";
}
}},
{name:'status', width:100,
editable: function (options) {
var item = $(this).jqGrid("getLocalRow", options.rowid);
return (item.Error_Cells_Count == null || item.Error_Cells_Count <= 0) &&
$.inArray(item.color_name, hilightcolorcell) >= 0 &&
$.inArray(item.character_name, hilightcahractercell) >= 0;
},
edittype:"select",editoptions:{value:"Approve:Approve"}},
{name:'note',width:100, sortable:false,editable: true,
edittype:"textarea", editoptions:{rows:"2",cols:"10"}},
{name:'color_name',
cellattr: function (rowid, cellValue) {
if ($.inArray(cellValue, hilightcolorcell) < 0) {
return " class='redcells'";
}
}},
{name:'character_name',
cellattr: function (rowid, cellValue) {
if ($.inArray(cellValue, hilightcahractercell) < 0) {
return " class='redcells'";
}
}},
{name:'v_id'}
],
cmTemplate: { width:110 }, // define default properties for colModel
editurl: "functions.php",
cellEdit: true,
cellsubmit: 'remote',
cellurl: 'functions.php',
searching: {
stringResult: true,
searchOnEnter: false,
defaultSearch : "cn"
}
}).jqGrid("setFrozenColumns")
.jqGrid("filterToolbar");

jqgrid select only one row per group

How can we allow the users to only select one row per group?
I have the following code.
var data = [
{ ActionItemId: "AAZ08702-0001104", StrarTime: "2007-10-01", Category: "General", CategoryDetails: "dummy text of industry. a galley of type ", TargetCategory: "200.00",
TargetDateCategory: "10.00", ActualCategory: "210.00"}
];
$("#jqGrid").jqGrid({
data: data,
datatype: "local",
colModel: [
{ label: 'Action Item ID', name: 'ActionItemId', key: true },
{ label: 'Start Time', name: 'StrarTime'},
{ label: 'Category', name: 'Category'},
{ label: 'Details', name: 'CategoryDetails', cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="white-space: normal;"' }},
{ label: 'Target <Category>', name: 'TargetCategory' },
{ label: 'Target Date <Category>', name: 'TargetDateCategory'}
],
loadonce: true,
viewrecords: true,
//width: 1000,
height: 400,
rowNum: 20,
rowList: [20, 30, 50],
rownumbers: true,
rownumWidth: 25,
multiselect: true,
shrinkToFit: false,
pager: "#jqGridPager",
grouping: true,
groupingView: {
groupField: ["Category"],
groupColumnShow: [true],
groupText: ["Category: <b>{0}</b>"],
groupOrder: ["asc"],
groupSummary: [false],
groupCollapse: false
}
});
I need to disable the ability to select multiple rows per column. is it possible?
Is there a setting in the grouping function to enable which will work as mu requirement? or should it be custom development?
Note: I have only added one column to avoid a very long code in the question
One of the possible implementation could be adding add callback which return false if another row from the same group is already selected. An example of the implementation is the following:
beforeSelectRow: function (rowid, e) {
var selarrrow = $(this).jqGrid("getGridParam", "selarrrow"),
$tr = $(e.target).closest("tr.jqgrow"),
otherIdsOfTheGroup;
if ($tr.length > 0) {
otherIdsOfTheGroup =
// get all rows of the group before the current
$tr.prevUntil("tr.jqgroup")
// add all rows of the group after the current
.add($tr.nextUntil("tr.jqgroup"))
// enum all the rows of the group without the current
.map(function () {
// test whether the rowid is already selected
if ($.inArray(this.id, selarrrow) >= 0) {
// add the rowid to the array of returned values
return this.id;
}
});
// otherIdsOfTheGroup contains the array of rowids of the rows
// from the same group, which are already selected
if (otherIdsOfTheGroup.length > 0) {
return false; // prevent selection
}
}
return true; // allow selection
}
See the demo
UPDATED: One can easy modify the aboce vode to unselect the previously selected rows from the same group. One need just call resetSelection for every rowid from otherIdsOfTheGroup array and return true from otherIdsOfTheGroup to allow selection:
beforeSelectRow: function (rowid, e) {
var $this = $(this),
selarrrow = $this.jqGrid("getGridParam", "selarrrow"),
$tr = $(e.target).closest("tr.jqgrow"),
otherIdsOfTheGroup;
if ($tr.length > 0) {
otherIdsOfTheGroup =
// get all rows of the group before the current
$tr.prevUntil("tr.jqgroup")
// add all rows of the group after the current
.add($tr.nextUntil("tr.jqgroup"))
// enum all the rows of the group without the current
.map(function () {
// test whether the rowid is already selected
if ($.inArray(this.id, selarrrow) >= 0) {
// add the rowid to the array of returned values
return this.id;
}
});
// otherIdsOfTheGroup contains the array of rowids of the rows
// from the same group, which are already selected
if (otherIdsOfTheGroup.length > 0) {
$.each(otherIdsOfTheGroup, function () {
$this.jqGrid("resetSelection", this);
});
}
}
return true; // allow selection
}
See the next demo. I included hiding of the column header of "Select All" button just to write less code. You can implement onSelectAll callback and allow to select only one (for example the first) row from every group.
I managed to solve this issue using the following code.
beforeSelectRow: function (id, e) {
var rowdata = $("#jqGrid").getRowData(id);
var category = rowdata.Category;
var selectedRowTR = $("#jqGrid").find("tr[id='" + id + "']");
var groupTRs = $("#jqGrid").find("tbody> tr.jqgrow > td[title='" + category + "']").parents("tr");
var ids = groupTRs.map(function () {
return this.id;
}).get();
var selectedIDs = $("#jqGrid").getGridParam("selarrrow");
var commonValues = [];
var i, j;
var arr1Length = ids.length;
var arr2Length = selectedIDs.length;
for (i = 0; i < arr1Length; i++) {
for (j = 0; j < arr2Length; j++) {
if (ids[i] === selectedIDs[j]) {
commonValues.push(ids[i]);
}
}
}
for (var i = 0; i < commonValues.length; i++) {
$("#jqGrid").jqGrid('setSelection', commonValues[i], false);
}
return true;
},
rowdata.Category; is the variable which the table is grouped. The only issue is that the user cannot untick what he/she has already selected in a group. so it works like a radio button set. But it works for my requirement.
hopefully we can improve this and introduce radio kind of behavior for grouping in jqgrid.
thanks everyone.

Client-side Generated KendoUI Grid is not highlighting selected row when grid is redisplayed

Client-side Generated KendoUI Grid is not highlighting selected row when grid is redisplayed (Kendo UI Complete v2013.1.514).
Kendoui grid is in a KendoUI Tab (Tab #1). Clicking on the 3rd row highlights the row. Clicking on the second tab (Tab #2) hides the grid tab and shows another grid. When clicking back on Tab #1 the first grid is redisplayed and the contents are shown.
When stepping through the tab onActivate(arg) function I can see using grid.select() that the row that was last selected is still the selected row however the row isn't highlighted.
I tried the following code in an attempt to reselect the row:
var element = $(WORK_PRODUCT),
grid = element.data("kendoGrid"),
row = element.find("tbody>tr[data-uid='" + grid.dataSource.get(_selectedWorkProduct).uid + "']");
grid.select(row);
I also examined the inner and outer HTML and the selected row matches exactly what was selected the first time the row was selected (TR class=k-state-selected role=row aria-selected=true data-uid="119b95c7-f3e4-4160-821e-507fbdc70026">7964
How can I visibly show that the row is selected? Thanks in advance!
Below is the code that initializes the grid:
DashViewUI.prototype.initWorkProducts = function (arg) {
$(WORK_PRODUCT).kendoGrid({
filterable: true
, sortable: true
, selectable: "row"
, pageable: true
, ajax: true
, columns:
[
{
field: "ID"
, title: ""
, sortable: true
, hidden: true
}
, {
field: "Number"
, title: "Case No."
, width: 80
, sortable: true
, filterable: true
}
, {
field: "Name"
, title: "Case Name"
, width: 120
, sortable: true
}
, {
field: "Status"
, title: "Status"
, width: 70
, sortable: true
}
]
, dataSource:
{
transport:
{
read:
{
url: AppPath + '/DashB/GetWorkProducts'
, contentType: 'application/json; charset=utf-8'
, type: 'GET'
, dataType: 'json'
}
}
, schema: {
model: {
id: "ID"
, fields: {
"ID": { type: "number" }
, "Number": { type: "string" }
, "Name": { type: "string" }
, "Status": { type: "string" }
}
}
}
}
, dataBound: function onDataBound(e) {
//alert('Data bound fired');
}
, change: function onCaseGridChange(arg) {
if (DEBUG)
debugger;
var cells = this.select();
var name = null;
if (cells.length > 0)
name = this.dataItem(cells[0]);
if (name.ID != null) {
// store the currently selected work product
_selectedWorkProduct = name.ID;
// refresh the party dial gauge
_dashViewUI.refreshDialGauge(PARTY_GAUGE, AppPath + '/DashB/GetCaseChildrenCount');
// reload the tasks for the selected work product
$(TASKS).data().kendoGrid.dataSource.read({ workProductID: _selectedWorkProduct });
}
}
});
};
The selected grid row will not be retained if you reload the grid. You have to store it before hand.
var selectedDataItem = grid.dataSource.getByUid(grid.select().data("uid"));
grid.dataSource.read();
if (selectedDataItem) {
var uid = grid.dataSource.get(selectedDataItem.id).uid;
grid.select('tr[data-uid="' + uid + '"]');
}
Here is a live demo: http://jsbin.com/USahiPor/1/edit

Add new row with a default value

I'm using the following code to fill one of the cells of a new row with a default value, but this is not working (the cell is empty). Is this code ok?
var parameters =
{
rowID: "new_row",
initdata: {
IdField: $('#IdField').val(),
Description: $('#IdField option:selected').text()
},
position: "first",
useDefValues: false,
useFormatter: false,
addRowParams: { extraparam: {} }
};
$("#containerGrid").jqGrid('addRow', rowid, parameters);
Problem solved by removing the rowid parameter from the addRow method.
$("#containerGrid").jqGrid('addRow', parameters);

jqGrid Set Selected Rows

I have a jqgrid with multiselect true and I want to set some of rows.(I know the row ids.) How can I do that?
I mean opposite of
$("#myTable").jqGrid('getGridParam', 'selarrrow');
as like:
$("#myTable").jqGrid('setGridParam', 'selarrrow', rowArray);
You have to loop through the rowArray array and call setSelection method for every rowid from the rowArray:
var i, count, $grid = $("#myTable");
for (i = 0, count = rowArray.length; i < count; i += 1) {
$grid.jqGrid('setSelection', rowArray[i], false);
}
$.each(rowsToSelect, function(_, rowId) {
$grid.setSelection(rowId, false);
});
No much difference. Just seemed neater :)
(Pretty amazing that even now, in 2014, jqGrid doesn't persist checkboxes when paging..)
Here's the code I needed to use, with jqGrid 4.4.5, to get the checkboxes to set, after moving to a new page:
var idsOfSelectedRows = []; // list of RowIDs for rows which have been ticked
$("#tblContracts").jqGrid({
...
colModel: [
{ name: 'AddContract', width: 50, align: "center", editable: true, edittype: 'checkbox', editoptions: { value: "True:False" }, formatter: "checkbox", formatoptions: { disabled: false } },
{ name: "ContractName", search: true, width: 80, align: "center" }
],
loadComplete: function () {
for (i = 0; i < idsOfSelectedRows.length; i++) {
$(this).setCell(idsOfSelectedRows[i], 'AddContract', true);
}
},
During development, I put an "alert" in that "for" loop. I found that using "setSelection" simply stepped through my list of RowIDs, selected the row (so it would become highlighted), then moved on to the next, selecting that one instead.
It didn't ever tick any of the checkboxes.
Notice that my "setCell" function includes the name of the jqGrid column where I have a checkbox.
If you cut'n'paste this code, make sure you change this line to reflect the name of your jqGrid checkbox column.

Resources