Is it possible to disable editing in jqGrid for certain cells in a column that is marked as editable?
From what I've seen, the only options are "all cells are editable" or "no cells are editable".
Is there a way to work around this?
I'll recommend you to use so named "Inline Editing" for row editing. The most advantage of this method, that it is very intuitive and the user. You can see how it works on the demo page http://trirand.com/blog/jqgrid/jqgrid.html. Choose on this demo "Row Editing" and then "Using Events" or "Input types" on the left tree part. With this method you can implement any custom verification whether the selected row should be allowed to be edited or not inside of the event handle onSelectRow or ondblClickRow. If you allow editing, then you call editRow method of jqGrid. This method creates input controls for all editable columns and the user can modify the row values in a natural way. The modifications will be saved if the user press "enter" key or canceled on "esc" key.
I personally prefer to implement calling of editRow method inside of ondblClickRow event handler. So the user can continue selecting of rows like usual and can use double click for the row editing. The pseudo code will look like folowing:
var lastSel = -1;
var isRowEditable = function (id) {
// implement your criteria here
return true;
};
var grid = jQuery('#list').jqGrid({
// ...
ondblClickRow: function(id, ri, ci) {
if (isRowEditable(id)) {
// edit the row and save it on press "enter" key
grid.jqGrid('editRow',id,true);
}
},
onSelectRow: function(id) {
if (id && id !== lastSel) {
// 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
grid.jqGrid('restoreRow',lastSel);
lastSel = id;
}
},
pager: '#pager'
}).jqGrid('navGrid','#pager',{edit:false});
You can do it logically. You must have some criteria for cells that some cells can be editable and some are not.
I have implemented it row wise.
When you create XML for jqgrid, give some id to each row.
Based on these ids you can make those rows' cells editable or noneditable using jqgrid methods.
Below is beforeEditCell method:
beforeEditCell: function(rowid, cellname, value, iRow, iCol) {
// here identify row based on rowid
// if the row should not be editable than simply make the cells noneditable using
editCell(iRow, iCol, false);
jQuery(gridid).jqGrid("restoreCell",iRow,iCol);
}
You can further implement yourself.
Hope my suggestion would help you. :)
Related
I am using jqgrid as grid with multiselect:true property. I want to remove checkbox for some rows based on some row value(disable/do not allow to check). I want to add formatter on checkbox model to remove checkbox on that column
I tried to access colModel inside beforeProcessing but i dont see the column name 'cb' autoadded by jqgrid yet. hence i cannot inject formatter inside the colmodel for 'cb'.
jqGrid({
multiselect: true,
beforeSelectRow: function() {
//called when tried to select one row.
//its not called when selectAll is called.
},
onSelectAll: function(rowids, status) {
//gets selected row ids when status is true
}
})
1) I want to manipulate selection of checkboxes based on row Value.
2) checkbox should not be (visible/selectable) if row with column isApplicable=false
jgrid version: 5.3.0
It's important that you always include the version of jqGrid, which you use (can use) in the text of your question. It's important to know the fork of jqGrid too (free jqGrid, commercial Guriddo jqGrid or an old jqGrid in version <=4.7).
Free jqGrid fork, which I develop, contains some options/callbacks which can be used to implement your requirements.
First of all you can use hasMultiselectCheckBox callback to inform jqGrid in which rows (based on the content from isApplicable column for example) multiselect checkbox should be created:
hasMultiselectCheckBox: : function (options) {
// options is object like below
// { rowid: rowid, iRow: irow, iCol: pos, data: item, checked: checked };
// one can use options.data to examine the data of the current row
return options.data != null && options.data.isApplicable;
}
Even if the checkbox not exist in the row one can still select the row by clicking on the row. (By the way, you can use multiselectPosition: "none" to have no column with multiselect checkboxs at all.) Thus you should add beforeSelectRow callback additionally, which prevent selection of the rows having isApplicable equal to false:
beforeSelectRow: function (rowid) {
var item = $(this).jqGrid("getLocalRow", rowid);
if (item != null && !item.isApplicable) {
return true;
}
return false;
},
alternatively, if you use one of the latest version of free jqGrid, you can use rowattr to add "jqgskipselect" class to rows, which should be not selectable:
rowattr: function (item) {
if (!item.isApplicable) {
return { "class": "jqgskipselect" };
}
},
free jqGrid prevent selection of rows, which have the class. In old versions you can use disabled class instead for preventing selection. It's "ui-state-disabled" class in case of usage jQuery UI CSS or "disabled" class in case of usage Bootstrap CSS.
Part 1) In my grid, I have some editable columns which I would like to do inline editing to. However when I select any particular cell and if the inline editing is available on that cell (editable: true), it should select the text to be edited.
For example if this is the default grid:
then upon selecting any cell in Quantity, the result should be something like this:
When we click on a cell to edit that row in jqGrid, current implementation does not highlight the selected text like this. Is there any way to achieve this?
Part 2) Migrated to this question as per Oleg's suggestion
GRID CODE: jsFiddle
Note: My real application datatype is JSON
I'm not sure about all versions of old web browsers, but you can modify the code of onSelectRow to the following
onSelectRow: function (id) {
var $self = $(this);
if (id && id !== lastsel2) {
$self.jqGrid('restoreRow', lastsel2);
$self.jqGrid('editRow', id, {
keys: true,
focusField: 'Quantity',
oneditfunc: function (rowid, options) {
$control = $("#" + rowid + "_Quantity");
if ($control.length > 0) {
$control[0].select();
}
},
aftersavefunc: reload
});
lastsel2 = id;
}
}
see http://jsfiddle.net/OlegKi/HJema/163/. It uses focusField: 'Quantity' option to set the focus on the 'Quantity' column. It uses select() method to select the text of <input> field.
The second part of your question (about bindKeys) seems to me a separate question. The method bindKeys allows to implement custom callbacks onLeftKey, onRightKey. Which one you would like better to use is not full clear for me.
I have three Tabs and in each tab, I have a Grid.
The data for each Grid is coming from a database, so I am using rowRenderer to populate the Grids. The following code is common for all three Grids:
<grid id="myGrid1" width="950px" sizedByContent="true" rowRenderer="com.example.renderer.MyRowRenderer">
The rows are constructed from Doublebox objects. The data is populated successfully.
The Problem:
I need to handle multiple-cell editing on the client side. The editing is done via mouse-clicking on a particular cell and entering a value.
As example let's say that the user edits first cell on the first row and the value should be
propagated to all other cells on the same row and in all three Grids (so also the two Grids which the user currently does not see, because they are in tabpanes).
I am using jQuery to do this value propagation and it works OK.
I am passing the jQuery as follows:
doublebox.setWidgetListener(Events.ON_CHANGING, jQuerySelectors);
doublebox.setWidgetListener(Events.ON_CHANGE, jQuerySelectors);
This makes it possible to change the value in 1 cell and the change is instantly (visually) seen in all other cells filtered by jQuery selectors.
The problem is that the value is visually distributed to all the cells, but when I try to save the Grid data back to the database, the background values are the old ones.
I am assuming that ZK-Grid component is not aware that jQuery changed all the cell values. Nevertheless if I manually click on a cell that already has the NEW value (enter/leave/change focus) when I save the grid the NEW value is correct in that particular cell. Maybe that's a hint how can I resolve this.
Code of how I extract the Grid values:
Grid tGrid = (Grid) event.getTarget().getFellow("myGrid1");
ListModel model = tGrid.getModel();
MyCustomRow tRow = (MyCustomRow)model.getElementAt(i);
The model for my Grid is a List of MyCustomRow:
myGrid1.setModel(new ListModelList(List<MyCustomRow> populatedList));
I have a couple of assumptions, but whatever I have tried, hasn't worked. I have in mind that jQuery events and ZK-Events are different and probably isolated in different contexts. (Although I have tried to fire events from jQuery and so on..)
Do you have any suggestions? As a whole is my approach correct or there's another way to do this? Thanks for your time in advance!
Your problem is exactly what you are expecting.
Zk has it's own event system and do not care about your jq,
cos it's jq and zk don't observ the DOM.
The ways to solve your problem.
Use the "ZK-Way":
Simply listen at server-side and chage things there.
I am not sure if not selected Tabs
are updateable, but I am sure you could update the Grid
components on the select event of the Tab.
Fire an zk-event your self:
All you need to know, is written in the zk doc.
Basically, you collect your data at client side, send
an Event to the server via zAu.send() extract the
data from the json object at serverside and update your Grids
I would prefer the first one, cos it's less work and there should not be
a notable difference in traffic.
I post the solution we came up with:
This is the javascript attached to each Doublebox in the Z-Grid
//getting the value of the clicked cell
var currVal = jq(this).val();
//getting the next cell (on the right of the clicked cell)
objCells = jq(this).parents('td').next().find('.z-doublebox');
// if there's a next cell (returned array has length) - set the value and
// fire ZK onChange Event
if (objCells.length) {
zk.Widget.$(jq(objCells).attr('id')).setValue(currVal);
zk.Widget.$(jq(objCells).attr('id')).fireOnChange();
} else { //otherwise we assume this is the last cell of the current tab
//So we get the current row, because we want to edit the cells in the same row in the next tabs
var currRow = jq(this).parents('tr').prevAll().length;
//finding the next cell, on the same row in the hidden tab and applying the same logic
objCellsHiddenTabs = jq(this).parents('.z-tabpanel').next().find('.z-row:eq(' + currRow + ')').find('.z-doublebox');
if (objCellsHiddenTabs.length) {
zk.Widget.$(jq(objCellsHiddenTabs).attr('id')).setValue(currVal);
zk.Widget.$(jq(objCellsHiddenTabs).attr('id')).fireOnChange();
}
}
The java code in the RowRenderer class looks something like this:
...
if (someBean != null) {
binder.bindBean("tBean", someBean);
Doublebox box = new Doublebox();
setDefaultStyle(box);
row.appendChild(box);
binder.addBinding(box, "value", "tBean.someSetter");
...
private void setDefaultStyle(Doublebox box) {
box.setFormat("#.00");
box.setConstraint("no negative,no empty");
box.setWidth("50px");
String customJS = ""; //the JS above
//this is used to visually see that you're editing multiple cells at once
String customJSNoFireOnChange = "jq(this).parents('td').nextAll().find('.z-doublebox').val(jq(this).val());";
box.setWidgetListener(Events.ON_CHANGING, customJSNoFireOnChange);
box.setWidgetListener(Events.ON_CHANGE, customJS);
}
What is interesting to notice is that ZK optimizes this fireOnChange Events and send only 1 ajax request to the server containing the updates to the necessary cells.
I have a table for adding a new budget details like the image below:
When I select an Income Account then another row is added to the viewmodel collection:
I want to set all field values to "0.00" when the new row is added and also I have a problem because if I delete a row then the "change" event of the combo doesnt exist so there is no way to add a new row when changing the last combo.
Any clue? Here is the fiddle working sample: http://jsfiddle.net/rLUyS/9/
Here is the code that I use to bind the change action to the last added combo:
$('select[name=cboincomeaccount_' + newRowIndex + ']').bind("change", {
combo: $(this)
}, handler);
function handler(event) {
newRowIndex++;
var combo = jQuery(this);
var row = combo.parent().parent();
appViewModel.addRow();
// Unbind
combo.unbind('change');
// Bind new combo
jQuery('select[name=cboincomeaccount_' + newRowIndex + ']').bind("change", {
combo: jQuery(this)
}, handler)
jQuery(row).find('input[name^="txtincmonth"]').removeAttr('disabled');
};
Thanks in advance!!
This might not be so much of a Knockout issue as it is a user interface issue.
I want to set all field values to "0.00" when the new row is added
Well that's easy enough. Simply initialize the the observable row to all zeros.
When I select an Income Account then another row is added to the viewmodel collection...
and also I have a problem because if I delete a row then the "change" event of the combo doesnt exist so there is no way to add a new row when changing the last combo.
This is probably a negotiable requirement.
Why not create an 'Add' button instead of insisting on this "nifty" behavior that adds a row when the user makes a section in the dropdown list?
Besides, even if we could accomplish what you're asking for (and I can envision a way that we could do this), what will you do when it's time to save the user's input to the server? Were you planning on ignore that last empty row?
I have a jQGrid with a column that I only want to be editable when adding a new row.
I've seen examples of how to do this when edits and adds are both happening in a dialog but is there a way to do this with in-line editing?
I've tried using grid.setColProp() in beforeShowForm:, but this doesn't work ( the column remains read only and is not present in the add dialog).
Example of dialog based column enable/disable:
http://www.ok-soft-gmbh.com/jqGrid/CustomFormEdit.htm
Because you use the example from my old answers (this and this) I feel that I should answer also on your question.
In the old example all fields, which can be modified during Add or Edit dialogs, has property editable:true. The fields which should be shown only in the Add dialog will be made hidden inside of beforeShowForm event handle. In the same way we can temporary switch some fields to editable:false before call of the editRow method and reset back to the editable:true immediately after the call:
onSelectRow: function(id) {
if (id && id !== lastSel) {
grid.jqGrid('restoreRow',lastSel);
var cm = grid.jqGrid('getColProp','Name');
cm.editable = false;
grid.jqGrid('editRow', id, true, null, null, 'clientArray');
cm.editable = true;
lastSel = id;
}
}
You can see this live here.
UPDATE: Free jqGrid allows to define editable as callback function. See the wiki article. It allows to make the column editable in some rows and holding non-editable for other rows.