jqGrid inline editing - addRow keys not working for the first time - jqgrid

I want to use inline editing with Esc and Enter keys and I'm using inlineNav method. I already set keys: true for editRow method and keys are working. While I'm usig "add row" button, keys are not forking for the first time. I must cancel this operation by mouse and when I tried to add row again, keys are working normally. I have no clue how to debug this. It's jqGrid v. 4.4.4
$("myGrid").jqGrid(finalConfig)
.navGrid(gridToolbar).inlineNav(gridToolbar, {
editParams: { keys: true }
}
);

If you want to define some common settings for inline editing I would recommend you to use $.jgrid.inlineEdit. For example
$.extend($.jgrid.inlineEdit, { keys: true });
In the case you will have Enter key working in any form of usage of inline editing. In the case inline editing activated per formatter: "actions" will works in the same way like Add and Edit buttons added by inlineNav.
Alternatively you have to specify special for inlineNav the option for "add row" button in the following way
$("#myGrid").jqGrid("inlineNav", "#pager", {
editParams: { keys: true },
addParams: { addRowParams: { keys: true } }
});
Typically one defines all inline editing options in one object and uses the same options object twice:
var editingOptions = { keys: true };
$("#myGrid").jqGrid("inlineNav", "#pager", {
editParams: editingOptions,
addParams: { addRowParams: editingOptions }
});
See the answer for more code examples.
UPDATED: I think I found the reason why you had keys: false used during Add operation at the beginning, but had later keys: false working. The reason is the bug which I described in the bug report which I just posted. You can try to use fixed version of jquery.jqGrid.src.js (you can get it here). The reason was that
inlineNav has one bug: it uses always editParams inside of "Cancel" event handler (see the line) even if we cancel "Add" operation. So the method restoreRow was called with editParams as parameter.
The next bug is that the line of restoreRow changes $.jgrid.inlineEdit instead of just usage it. To fix the bug one have to change the line
o = $.extend(true, $.jgrid.inlineEdit, o );
to
o = $.extend(true, {}, $.jgrid.inlineEdit, o);

Related

HandsOnTable Dropdown Without Editable Text?

Is it possible to use a dropdown column in a HandsOnTable without the editable textbox?
I know you can set the type to dropdown and it will validate/highlight red when you enter an invalid value, but is there a way to completely disable text entry for dropdown columns? It seems just using the readOnly property on the column blocks the dropdown altogether.
As you said, the readOnly option will disable you dropdown. So I believe the closest solution you can use is the allowIndvalid = false (true by default) :
allowInvalid: true (optional) - allows manual input of value that does not exist in the source. In this case, the field background highlight becomes red and the selection advances to the next cell
allowInvalid: false - does not allow manual input of value that does not exist in the source. In this case, the ENTER key is ignored and the editor field remains opened.
Documentation Link
You can use this JSFiddle to quickly check this option
I have the same issue and was able to resolve it with such steps. Maybe this could help:
1 when creating columns add a special className to the necessary column type:
{
data: 'priceUnitsName',
type: 'dropdown',
invalidCellClassName: 'colored',
source: Object.keys(unitNames),
width: 100,
className: 'disable-edit',
}
2 Subscribe to events to handle cancel editing:
private targetCell: HTMLTableCellElement;
public settings: GridSettings = {
// your settings
afterOnCellMouseDown: (event: MouseEvent, coords: CellCoords, TD: HTMLTableCellElement) => {
this.targetCell = TD;
},
afterBeginEditing: (row: number, column: number) => {
if (this.targetCell.classList.contains('disable-edit')) { // this handle only necessary columns with special class
setTimeout(() => {
const inputCollection: HTMLCollection = document.getElementsByClassName('handsontableInput');
Array.from(inputCollection).forEach((input: HTMLTextAreaElement) => {
input.blur(); // this calls blur on element manually
});
});
}
},
Maybe this is not the best decision, but by default, handsontable can't make dropdown elements readonly with leaving open-close dropdown functional and I can't find any workable suggestion with this.
Checked on 'dropdown' and 'date' types, and it works.

Dynamically change a column's editable property with select box

I am using form editing. I would like to disable certain fields in my add and edit forms based on the selection from a drop down box. What event is best to use to trigger this? I have attempted using dataEvents:
{ name:'type_cd',
edittype:'select',
editoptions:{
dataUrl:'functions.php',
dataEvents:[{
type:'change',
fn: function(e){
$(this).setColProp('cntrct_id',{
editoptions:{editable:false}
});
}
}]
}
},
This has no visible effect on my form fields, but I know that it's being reached because I can get an alert message from it if I put one in.
EDIT
If I submit the form, the next time I open it, the column that was set to editable:false will not appear. This is a step in the right direction, BUT I want it to immediately be uneditable. Really, I would like it to be visible, but disabled (i.e. disabled:true)
First of all dataEvents allows you to register callbacks on elements of edit elements. Inside of callbacks this will be initialized to the DOM element which will be bound. So $(this) inside of change handler it will be wrapper on <select> element and not on the grid. The usage of $(this).setColProp will be incorrect.
To disable some input field in Add/Edit form you can use the fact that all input elements get the same id like the value of name property on the corresponding column in colModel. So if you need to disable input of cntrct_id you can set disabled property to true on the element with id="cntrct_id"
{
name: 'type_cd',
edittype: 'select',
editoptions: {
dataUrl: 'functions.php',
dataEvents: [{
type: 'change',
fn: function (e) {
// disable input/select field for column 'cntrct_id'
// in the edit form
$("#cntrct_id").prop("disabled", true);
}
}]
}
}
It's important to understand that editoptions will be used for any existing editing modes (form editing, inline editing and cell editing). If you want to write the code of dataEvents which supports all editing modes you have to detect editing mode and use a little other ids of editing fields. The code (not tested) can be about as below
{
name: 'type_cd',
edittype: 'select',
editoptions: {
dataUrl: 'functions.php',
dataEvents: [{
type: 'change',
fn: function (e) {
var $this = $(e.target), $td, rowid;
// disable input/select field for column 'cntrct_id'
if ($this.hasClass("FormElement")) {
// form editing
$("#cntrct_id").prop("disabled", true);
} else {
$td = $this.closest("td");
if ($td.hasClass("edit-cell") {
// cell editing
// we don't need to disable $("#cntrct_id")
// because ONLY ONE CELL are edited in cell editing mode
} else {
// inline editing
rowid = $td.closest("tr.jqgrow").attr("id");
if (rowid) {
$("#" + $.jgrid.jqID(rowid) + "_cntrct_id")
.prop("disabled", true);
}
}
}
}
}]
}
}
The last remark. If you still use old version of jQuery (before jQuery 1.6) which don't support prop method you have to use attr instead.
#Oleg: This is working(could get the alert messages) but its not disabling the field.
Should the form field require any special values?

JQGrid: Dependency Dropdown in dataEvents Change

I am developing a grid that contains a list of permits per module.
What I want is to validate every 2 events when a change is made in a combobox in a column. I'm using 1 and 0 for activating / deactivating
The first case: If I active "write", "modify", "delete" or "print" means that self-select "read"
The second case is the opposite: If you disable "Read" will turn off automatically "write", "modify", "delete" and "print"
Researching I found the option to use functions of input events:
{"name":"read",
"index":"read",
"width":48,
"resizable":false,
"editable":true,
"edittype":"select",
"editoptions":{
"value":"0:0;1:1",
"dataEvents":[{
"type":"change",
"fn":function(e){
if($(e.target).val() == '0')
{
// actions here...
}
}
}]
}
}
You can change the elements of the other columns ... by row?
EDIT
my solution:
$('tr.jqgrow select[name*="read"]').live("change",function()
{
if($(this).val() === '0') $(this).closest('tr.jqgrow').find('select.editable').not(this).find('option:first-child').attr("selected", "selected");
});
$('tr.jqgrow select[name!="read"]').live("change",function()
{
$(this).closest('tr.jqgrow').find('select[name*="read"]').find('option:last-child').attr("selected", "selected");
});
In the answer you will find an example how to implement dependent selects in jqGrid. By the way you can use the same idea with formatter: "checkbox". In the case the implementation will be much easier. It's important that you have to modify the <select> elements or chachboxes manually.
One more answer can you show another implementation option which you can use.

In jqGrid do I have to manually call saveRow to trigger an ajax save request?

The documentation here is not very clear:
http://www.trirand.com/jqgridwiki/doku.php?id=wiki:inline_editing&s[]=editurl#saverow
Do I have to manually make a saveRow call after the user finishes editing a table cell/row, or will jqGrid automatically trigger saveRow when the row (cell?) loses focus?
I'm giving jqGrid a editurl value in the initial setup, but I don't see any ajax requests going out when I finish editing a row.
You have two options:
You use editRow with the parameter keys: true. In the case the method saveRow will be called if the user press Enter and the method restoreRow will be called if the user press Esc. In the case you don't need to call saveRow explicitly. Inside of onSelectRow one calls typically restoreRow see here an example.
You can call saveRow instead of restoreRow in the onSelectRow callback. Additionally (or alternatively) you can gives the user an interface to save current editing row. It can be some kind of "Save" button.
Although that's an old question, I'd like to add an example of explicitly calling editRow and then saveRow, which is a pretty frequent case.
The following code allows the user to just move freely between selected rows, and save the previous selected, edited row:
var grid = $('#gridName').jqGrid({
// ... some grid properties ...
editurl: 'clientArray',
cellEdit: false, // that's the default, but just to make clear that wer'e in inline edit mode
onSelectRow: utils.onSelectRow
// ... some more grid properties ...
});
var utils = {
prevRowId: null, // we have to keep the previous row id
onSelectRow: function (rowId, selectionStatus, event) {
if (rowId && rowId !== utils.prevRowId) {
var $grid = $(event.target).closest('table');
$grid.jqGrid('saveRow', utils.prevRowId);
$grid.jqGrid('editRow', rowId, { keys: true });
utils.prevRowId = rowId;
}
},
};
I couldn't find one of Oleg's official examples doing exactly this (they're all using buttons, as this one, or calling retrieveRow instead of saveRow, as this one).

JQGrid - toggling multiselect

Is there a way to toggle the multiselect option of a grid?
Changing the multiselect parameter of the grid and calling for a reload has the side-effect of leaving the header behind when disabling or not creating the header column if multiselect was not TRUE upon the grid creation.
The closest I have come is setting multiselect to TRUE upon grid creation and using showCol and hideCol to toggle: $('#grid').showCol("cb").trigger('reloadGrid');
This has a side effect of changing the grid width when toggled. It appears the cb column width is reserved when it is not hidden.
Basically I'm attempting to create a grid with an "edit/cancel" button to toggle the multiselect -- very similar to how the iPhone/iPad handles deleting multiple mail or text messages.
Thank you in advance.
I full agree with Justin that jqGrid don't support toggling of multiselect parameter dynamically. So +1 to his answer in any way. I agree, that the simplest and the only supported way to toggle multiselect parameter will be connected with re-initialize (re-creating) the grid.
So if you need to change the value of multiselect parameter of jqGrid you need first change multiselect parameter with respect of respect setGridParam and then re-creating the grid with respect of GridUnload method for example. See the demo from the answer.
Nevertheless I find your question very interesting (+1 for you too). It's a little sport task at least to try to implement the behavior.
Some remarks for the understanding the complexity of the problem. During filling of the body of the grid jqGrid code calculate positions of the cells based on the value of multiselect parameter (see setting of gi value here and usage it later, here for example). So if you will hide the column 'cb', which hold the checkboxes, the cell position will be calculated wrong. The grid will be filled correctly only if either the column 'cb' not exists at all or if you have multiselect: true. So you have to set multiselect: true before paging or sorting of the grid if the column 'cb' exist in the grid. Even for hidden column 'cb' you have to set multiselect to true. On the other side you have to set multiselect to the value which corresponds the real behavior which you need directly after filling of the grid (for example in the loadComplete).
I hope I express me clear inspite of my bad English. To be sure that all understand me correctly I repeat the same one more time. If you want try to toggle multiselect dynamically you have to do the following steps:
create grid in any way with multiselect: true to have 'cb' column
set multiselect: false and hide 'cb' column in the loadComplete if you want to have single select behavior
set multiselect: true always before refreshing the grid: before paging, sorting, filtering, reloading and so on.
I created the demo which seems to work. It has the button which can be used to toggle multiselect parameter:
In the demo I used the trick with subclassing (overwriting of the original event handle) of reloadGrid event which I described the old answer.
The most important parts of the code from the demo you will find below:
var events, originalReloadGrid, $grid = $("#list"), multiselect = false,
enableMultiselect = function (isEnable) {
$(this).jqGrid('setGridParam', {multiselect: (isEnable ? true : false)});
};
$grid.jqGrid({
// ... some parameters
multiselect: true,
onPaging: function () {
enableMultiselect.call(this, true);
},
onSortCol: function () {
enableMultiselect.call(this, true);
},
loadComplete: function () {
if (!multiselect) {
$(this).jqGrid('hideCol', 'cb');
} else {
$(this).jqGrid('showCol', 'cb');
}
enableMultiselect.call(this, multiselect);
}
});
$grid.jqGrid('navGrid', '#pager', {add: false, edit: false, del: false}, {}, {}, {},
{multipleSearch: true, multipleGroup: true, closeOnEscape: true, showQuery: true, closeAfterSearch: true});
events = $grid.data("events"); // read all events bound to
// Verify that one reloadGrid event hanler is set. It should be set
if (events && events.reloadGrid && events.reloadGrid.length === 1) {
originalReloadGrid = events.reloadGrid[0].handler; // save old
$grid.unbind('reloadGrid');
$grid.bind('reloadGrid', function (e, opts) {
enableMultiselect.call(this, true);
originalReloadGrid.call(this, e, opts);
});
}
$("#multi").button().click(function () {
var $this = $(this);
multiselect = $this.is(":checked");
$this.button("option", "label", multiselect ?
"To use single select click here" :
"To use multiselect click here");
enableMultiselect.call($grid[0], true);
$grid.trigger("reloadGrid");
});
UPDATED: In case of usage jQuery in version 1.8 or higher one have to change the line events = $grid.data("events"); to events = $._data($grid[0], "events");. One can find the modified demo here.
I really like what you are trying to do here, and think it would be a great enhancement for jqGrid, but unfortunately this is not officially supported. In the jqGrid documentation under Documentation | Options | multiselect you can see the Can be changed? column for multiselect reads:
No. see HOWTO
It would be nice if there was a link or more information about that HOWTO. Anyway, this is probably why you are running into all of the weird behavior. You may be able to work around it if you try hard enough - if so, please consider posting your solution here.
Alternatively, perhaps you could re-initialize the grid in place and change it from/to a multi-select grid? Not an ideal solution because the user will have to wait longer for the grid to be set up, but this is probably the quickest solution.
A simpler answer:
<input type="button" value="Multiselect" onclick="toggle_multiselect()">
<script>
function toggle_multiselect()
{
if ($('#list1 .cbox:visible').length > 0)
{
$('#list1').jqGrid('hideCol', 'cb');
jQuery('.jqgrow').click(function(){ jQuery('#list1').jqGrid('resetSelection'); this.checked = true; });
}
else
{
$('#list1').jqGrid('showCol', 'cb');
jQuery('.jqgrow').unbind('click');
}
}
</script>
Where list1 is from <table id="list1"></table>.

Resources