I want to select and unselect a row multiple times by clicking.
My code is so far: (lastSelected is a global var):
beforeSelectRow: function (id)
{
if (lastSelected !== id)
{
grid.setSelection(id);
lastSelected = id;
return;
}
else
{
grid.resetSelection(id);
lastSelected = null;
}
}
The code works fine, but row is highlighted only after first click. The Second click unhighlight it and it keep being unhighlighted when I click it next times, but after 3rd, 5th... clicks it behave like selected (I have modal which pops up when row is selected), but is not highlighted.
Without grid.getSelection(id) it won't highlight at all, but still working like it was selecting and deselecting.
It seems to me that the main error in your code is the returned value of beforeSelectRow. If the returned value in not false then the standard processing will be continued and the row which you previously selected explicitly by usage setSelection can be unselected.
To fix the problem you should return false from beforeSelectRow. Additionally I would suggest to use $(this) instead of grid variable and to use standard selrow parameter of jqGrid instead of usage lastSelected variable. The resulting code could be the following
beforeSelectRow: function (rowid, e) {
var $self = $(this), selectedRowid = $self.jqGrid("getGridParam", "selrow");
if (selectedRowid === rowid) {
$self.jqGrid("resetSelection");
} else {
$self.jqGrid("setSelection", rowid, true, e);
}
return false; // don't process the standard selection
}
The corresponding demo is here.
Related
I have 2 bootstrap-multiselect boxes. I want to refresh the items in one based on the selections made in the other via an Ajax call.
Everything work except that the that the multiselect uses to disoplay the options is not being populated by either 'rebuild' or 'refresh'.
Code:
Decalring the multiselect"
$('#Groups').multiselect({
onChange: function (option, checked) {
//get all of the selected tiems
var values = $('#Groups option:selected');
var selected = "";
$(values).each(function (index, value) {
selected += $(value).prop('value') + ",";
});
selected = selected.substring(0, selected.length - 1);
//update hidden field with comma delimited string for state persistance
$("#Hidden_Groups").val(selected);
},
includeSelectAllOption: true
});
Updating the options list:
$('#JobCodes').multiselect({
onDropdownHide: function(event) {
console.log("start");
var option = $("#Groups");
//clear out old consolidations
option.empty();
console.log("emptied");
////get consolidation and append to select options list
$.getJSON("/Reports/GetGroups/", { options: $("#Hidden_JobCodes").val() }, function (result) {
$.each(result, function (index, item) {
console.log(item.text);
option.append($("<option />").val(item.id).text(item.text));
});
});
option.multiselect('destroy');
option.multiselect('rebuild');
option.multiselect('refresh');
},
Have left the destroy, rebuild and refresh in just as an example things i have tried. Have used all of these in every order and combination and no luck.
Destroy will "change" my multiselect back to a standard select but no matter what I do after that I cannot get the multiselect to come back with the new list of options, including using the full multiselect call wiht the onchange event present. Its either empty of has the old list. The select list has the correct options present when I make the refresh/rebuild calls.
Thanks in advance.
T
Totally my fault!!
The call to /destroy/refresh/rebuild was outside of the ajax call. so the were executing before my new list had been returned, hence no list to rebuild at that time.
Solution:
////get consolidation and append to select options list
$.getJSON("/Reports/GetGroups/", { options: $("#Hidden_JobCodes").val() }, function (result) {
$.each(result, function (index, item) {
console.log(item.text);
option.append($("<option />").val(item.id).text(item.text));
});
option.multiselect('rebuild')
});
Assume that row numbers is changed from 10 to 30 in navgrid and that we handle onPaging like so:
...
onPaging: function(pgbtn) {
var rowNum = $(this).getGridParam('rowNum');
return 'stop';
}
In jqGrid 4.4.0 rowNum will be 30.
In jqGrid 4.7.0 rowNum will be 10.
Is this expected behaviour because I think rowNum should be 30?
The order of the execution is changed in (compare the line in jqGrid 4.7.0 with the line in jqGrid 4.4.0). jqGrid first changed the rowNum``and then calledonPaging` in jqGrid 4.4.0, but in jqFeid 4.7.0 the oder is changed.
To access to the new value of rowNum one should get the value of rowNum from the corresponding <select> control directly. If you use the pager at the bottom of the grid then the corresponding code could be the following:
onPaging: function (pgButton) {
var p = $(this).jqGrid("getGridParam"),
newRowNum = parseInt($(p.pager).find(".ui-pg-selbox").val());
if (...) { // some stop criteria
return "stop";
}
}
If you use toppager: true option then jqGrid create the pager on the top of the grid and then it change the value of toppager parameter from true to the selector id of the pager. So you can use the code like
onPaging: function (pgButton) {
var p = $(this).jqGrid("getGridParam"),
newRowNum = parseInt($(p.toppager).find(".ui-pg-selbox").val());
if (...) { // some stop criteria
return "stop";
}
}
which just use p.toppager instead of p.pager in the previous code example.
In case of usage both top and bottom pagers you have to get both values and choose the value which is not equal to the value of rowNum parameter:
onPaging: function (pgButton) {
var p = $(this).jqGrid("getGridParam"),
rowNumBottom = parseInt($(p.pager).find(".ui-pg-selbox").val()),
rowNumTop = parseInt($(p.toppager).find(".ui-pg-selbox").val()),
newRowNum = p.rowNum === rowNumTop ? rowNumBottom: rowNumTop;
if (...) { // some stop criteria
return "stop";
}
}
By the way there are exist close problem in case of calling onPaging after other changing in the pager, for example if the user typed new value in the input box with new pager number.
I'm developing now free jqGrid as my fork on github. I change the code of jqGrid so that onPaging receives the second parameter which is object with the properties newPage, currentPage, lastPage, currentRowNum and newRowNum. The corresponding jQuery event jqGridPaging are added too. Moreover I have changed the value of the first parameter so that it corresponds the documentation and the value will be the string "first", "last", "prev" or "next" in case when the user clicked on the corresponding pager button. The version 4.7 used in reality the id of the corresponding pager buttons instead of "first", "last", "prev", "next". So the strings "first", "last", "prev", "next" could be appended with "_" and the id of the pager (or toppager).
Thus one can just use options.newRowNum or options.currentRowNum directly in the code of callback:
onPaging: function (pgButton, options) {
// one can use options.newRowNum directly
// the value options.currentRowNum is identical to
// $(this).jqGrid("getGridParam", "rowNum")
if (...) { // some stop criteria
return "stop";
}
}
In the case of top and bottom pagers, I would add to Oleg's response:
onPaging: function (pgButton) {
var p = $(this).jqGrid("getGridParam"),
rowNumBottom = parseInt($(p.pager).find(".ui-pg-selbox").val()),
rowNumTop = parseInt($(p.toppager).find(".ui-pg-selbox").val()),
newRowNum = p.rowNum === rowNumTop ? rowNumBottom: rowNumTop;
if (...) { // some stop criteria
return "stop";
}
// update the current value so subsequent changes are detected
p.rowNum = newRowNum;
}
This handles the case that the user changes the value on the top pager, then changes it again on the bottom pager. The code above will keep detecting the top pager value.
I have a scenario where I have a Kendo dropdown, Kendo Datepicker as couple of columns in the grid.
On Add new record, the dropdown should be editable, on Edit mode, this drop down should be non Editable.
I have declared Grid to be Editable in declaration using
.Editable()
model.Field(p => p.CountryName).Editable(true); // where CountryName is kendo dropdown
I am trying to do on Edit this way,
function OnEdit(e) {
if (e.model.isNew() == false) {
e.model.fields["CountryName"].editable = false
}
THe behaviour I observe is Initially on load, Editable is set to true (due to cshtml declaration). When I click on Edit too, the drop down is Editable because of the page load flag that is set.
Even though OnEditmethod is executed and editable is set to false, the grid seems to have loaded before this code execution, hence editable =false is not reflected.
If I click on Edit second time, now the editable is set to false due to the previous call, Hence the dropdown is non editable as expected.
In Summary, the flag setting is not effective for the current action, but for the immediate next action. I am not sure if I have made it clear. Can you guys help?
Update - The other option I tried, during databind to the grid, I tried explicitly settign editable to false to all the grid data. My assumption here was only the loaded rows will have this field set to false. But in this case even the add new record takes Editable false.
var grid2 = $("#Gridprepayment").data("kendoGrid").dataSource.data(requiredData);
$.each(requiredData, function (i, row) {
var model = $("#Gridprepayment").data("kendoGrid").dataSource.at(i);
if (model) {
model.fields["CountryName"].editable = false;
}
});
The best way is to make the column editable .
e.g.
model.Field(d => d.CountryName).Editable(true);
and Onedit function, replace the inner html like mentioned below, for just to display it as label.
function OnEdit(e) {
e.container[0].childNodes['0'].innerHTML = e.model.CountryName;
}
Try disabling the kendo dropdown in the following manner:
function OnEdit(e) {
if (e.model.isNew() == false) {
$("#CountryName").data("kendoDropDownList").enable(false);
}
}
You can try this if you want to show the dropdownList as label in edit mode
function OnEdit(e) {
if(e.container.find("input").attr("id") === 'CountryName') {
this.closeCell();
}
}
Note: The above code was written considering "CountryName" as the id of the dropdown. Please change if the id is different.
I tried this which worked.
It's only a work around :
function OnEdit(e) {
if (e.model.isNew() == false) {
if (e.container.find("input").attr("id") === 'CountryName') {
e.container.find("td:eq(0)").html($("#CountryName").val());
}
}
}
I am using a custom formatter to create hyperlinks in one of the columns of my grid.
In my code, there are cases when I need to disable the selected row. The row disabling works as I want it to, but the hyperlink for that row is not disabled. I can not select the row and all the other column values are displayed as grey colored to indicate that the row is disabled. The only column whose content does not change color is the one having links.
Any ideas on how to disable links?
This is my loadComplete function:
loadComplete: function (data) {
var ids =jQuery("#list").jqGrid('getDataIDs');
for(var i=0;i < ids.length;i++){
var rowId = ids[i];
var mod = jQuery("#list").jqGrid('getCell',ids[i],'mod');
if(mod=='y'){
jQuery("#jqg_list_"+rowId).attr("disabled", true);
$("#list").jqGrid('setRowData',ids[i],false, {weightfont:'bold',color:'silver'});
var iCol = getColumnIndexByName.call(this, 'adate');
$(this).jqGrid('doInEachRow', function (row, rowId, localRowData) {
$(row.cells[iCol]).children("a").click(function (e) {
e.preventDefault();
// any your code here
alert("No Good");
return false;
});
});
}
}
}
I want the links disabled in all the rows where the value of the column mod=y
You can try to use onClick callback of dynamicLink formatter described here, here and here. It gives you maximum flexibility. Inside of onClick callback you can test something like $(e.target).closest("tr.jqgrow").hasClass("not-editable-row") and just do nothing in the case.
When I create a checkbox column (through use of formatters/editors) in Slickgrid, I've noticed that it takes two clicks to interact with it (one to focus the cell, and one to interact with the checkbox). (Which makes perfect sense)
However, I've noticed that I am able to interact with the checkbox selectors plugin (for selecting multiple rows) with one click. Is there any way I can make ALL of my checkboxes behave this way?
For futher readers I solved this problem by modifing the grid data itself on click event. Setting boolean value to opposite and then the formatter will display clicked or unclicked checkbox.
grid.onClick.subscribe (function (e, args)
{
if ($(e.target).is(':checkbox') && options['editable'])
{
var column = args.grid.getColumns()[args.cell];
if (column['editable'] == false || column['autoEdit'] == false)
return;
data[args.row][column.field] = !data[args.row][column.field];
}
});
function CheckboxFormatter (row, cell, value, columnDef, dataContext)
{
if (value)
return '<input type="checkbox" name="" value="'+ value +'" checked />';
else
return '<input type="checkbox" name="" value="' + value + '" />';
}
Hope it helps.
The way I have done it is pretty straight forward.
First step is you have to disable the editor handler for your checkbox.
In my project it looks something like this. I have a slickgridhelper.js to register plugins and work with them.
function attachPluginsToColumns(columns) {
$.each(columns, function (index, column) {
if (column.mandatory) {
column.validator = requiredFieldValidator;
}
if (column.editable) {
if (column.type == "text" && column.autocomplete) {
column.editor = Slick.Editors.Auto;
}
else if (column.type == "checkbox") {
//Editor has been diasbled.
//column.editor = Slick.Editors.Checkbox;
column.formatter = Slick.Formatters.Checkmark;
}
}
});
Next step is to register an onClick event handler in your custom js page which you are developing.
grid.onClick.subscribe(function (e, args) {
var row = args.grid.getData().getItems()[args.row];
var column = args.grid.getColumns()[args.cell];
if (column.editable && column.type == "checkbox") {
row[column.field] = !row[column.field];
refreshGrid(grid);
}
});
Now a single click is suffice to change the value of your checkbox and persist it.
Register a handler for the "onClick" event and make the changes to the data there.
See http://mleibman.github.com/SlickGrid/examples/example7-events.html
grid.onClick.subscribe(function(e, args) {
var checkbox = $(e.target);
// do stuff
});
The only way I found solving it is by editing the slick.checkboxselectcolumn.js plugin. I liked the subscribe method, but it haven't attached to me any listener to the radio buttons.
So what I did is to edit the functions handleClick(e, args) & handleHeaderClick(e, args).
I added function calls, and in my js file I just did what I wanted with it.
function handleClick(e, args) {
if (_grid.getColumns()[args.cell].id === _options.columnId && $(e.target).is(":checkbox")) {
......
//my custom line
callCustonCheckboxListener();
......
}
}
function handleHeaderClick(e, args) {
if (args.column.id == _options.columnId && $(e.target).is(":checkbox")) {
...
var isETargetChecked = $(e.target).is(":checked");
if (isETargetChecked) {
...
callCustonHeaderToggler(isETargetChecked);
} else {
...
callCustonHeaderToggler(isETargetChecked);
}
...
}
}
Code
pastebin.com/22snHdrw
Search for my username in the comments
I used the onBeforeEditCell event to achieve this for my boolean field 'can_transmit'
Basically capture an edit cell click on the column you want, make the change yourself, then return false to stop the cell edit event.
grid.onBeforeEditCell.subscribe(function(row, cell) {
if (grid.getColumns()[cell.cell].id == 'can_transmit') {
if (data[cell.row].can_transmit) {
data[cell.row].can_transmit = false;
}
else {
data[cell.row].can_transmit = true;
}
grid.updateRow(cell.row);
grid.invalidate();
return false;
}
This works for me. However, if you're using the DataView feature (e.g. filtering), there's additional work to update the dataview with this change. I haven't figured out how to do that yet...
I managed to get a single click editor working rather hackishly with DataView by calling
setTimeout(function(){ $("theCheckBox").click(); },0);
in my CheckBoxCellEditor function, and calling Slick.GlobalEditorLock.commitCurrentEdit(); when the CheckBoxCellEditor created checkbox is clicked (by that setTimeout).
The problem is that the CheckBoxCellFormatter checkbox is clicked, then that event spawns the CheckBoxCellEditor code, which replaces the checkbox with a new one. If you simply call jquery's .click() on that selector, you'll fire the CheckBoxCellEditor event again due because slickgrid hasn't unbound the handler that got you there in the first place. The setTimeout fires the click after that handler is removed (I was worried about timing issues, but I was unable to produce any in any browser).
Sorry I couldn't provide any example code, the code I have is to implementation specific to be useful as a general solution.