Multiple checkbox columns in jqgrid. Handle onchange event - javascript

I am creating a jqgrid with editable fields. I have 2 checkbox columns in jqgrid, one is coming from multiselect: true (to get unique rowId), other column is created inside column model.
I want to handle the onchange(checked/unchecked) event of the checkbox in my column model, independent of other checkbox column(multiselect:true). Any help appreciated. Below is the code snippet.
[{name : "userRole", label: 'OV', width: 40, editable:true, edittype:'checkbox',formatter: 'checkbox', editoptions: {value:"True:False"},
formatoptions: { disabled: false},frozen:true}]
multiselect: true,
onSelectRow: function(rowid){
jQuery(this).editRow(rowid, true);
}

You can use beforeSelectRow callback. The demo demonstrate the approach. It uses the following code
beforeSelectRow: function (rowid, e) {
var $target = $(e.target), $td = $target.closest("td"),
iCol = $.jgrid.getCellIndex($td[0]),
colModel = $(this).jqGrid("getGridParam", "colModel");
if (iCol >= 0 && $target.is(":checkbox")) {
alert("checkbox is " +
($target.is(":checked")? "checked" : "unchecked") +
" in the column \"" + colModel[iCol].name +
"\" in the row with rowid=\"" + rowid + "\"");
}
return true;
}

Define your own formatter function like this in your colmodel,
[{name : "userRole", label: 'OV', width: 40,
editable:true, edittype:'checkbox',formatter: checkboxFormatter,
editoptions: {value:"True:False"},
And your formatted checkbox like,
function checkboxFormatter(cellvalue, options, rowObject) {
return "<input type='checkbox' name='checkboxIsCC'
onchange='your_own_function();'>";
}
Hope this helps you.

I had an issue were not only I had more than 1 check box but also I had to update same column check box values based on the selection of the check box as well as modifying the same row columns.
In regards to the modification of the other checkboxes, when jqgrid modifies the data either by 'setCell' or 'setRowData' operations, it removes the click event. Also there is the problem that for checkboxes none of the edit functions are useful.
I manage to get bits from other people's solution and came to use the delegate jquery functions, that allows the binding of the click to be done each time an object that matches the selector is created. Also in this case only 1 checkbox of only 1 column could be checked at a time.
$(document).delegate("#alarmDownloadListView td[aria-describedby*='stopArm'] input", 'click', function () {
// Function that modifies all the other checkboxes of the same column
deselectOthersStopArmAlarms(this, j);
// Set the Pre and Pos Alarm values to default
var fileIndex = $(this).closest('tr').index();
// Modification of the same row cells
if($(this).is(':checked')){
alarmsGrid.jqGrid('setCell',fileIndex,'preAlarm', defaultPrePosStopArmAlarmValue);
}else{
alarmsGrid.jqGrid('setCell',fileIndex,'preAlarm', null);
}
});
Do not mind the exact operations of the code, what is important is the operations that the binded function does. The CSS selector binds this function to all checkboxes whose name in my colmodel is stopArm.
I hope this answer is useful for some people. I found the delegate to be very useful! :)

Related

Kendo UI Grid editable manual dataItem.set() slow/delay

I have an editable Kendo Grid that may have a column with a checkbox to change a boolean value. I have used this solution proposed by OnaBai that is working perfectly!
The only problem is that the checkbox value change is too slow. When user clicks it, it takes about 1 second to change. I realize that the dataItem.set() method is responsible by this delay.
My grid has a considerable amount of data. About 30-40 columns and 300+ lines. It is defined as follows:
$("#mainGrid").kendoGrid({
dataSource: dataSource,
pageable: false,
sortable: true,
scrollable: true,
editable: true,
autoBind: false,
columnMenu: true, // Cria o menu de exibição de colunas
height: getGridHeight(),
toolbar: [/* hide for brevity */],
columns: [/* hide for brevity */],
dataBound: function() { /* hide for brevity. */},
edit: function() { /* hide for brevity. */}
});
Another detail is that, when dataItem.set() is called, it calls dataBound() event but that is not causing the delay. Grid's edit() method is not being called on this process. I don't know if worths to post dataSource code.
I would suggest using the approach from this code library article when it comes to use checkboxes. It does not use the set methods of the model and still works the same way. Even with 2000 records on a single page CheckAll will work flawlessly.
I have found an alternative way for doing what OnaBai proposed and it's working better.
// This is the grid
var grid = $("#mainGrid").data("kendoGrid");
// .flag is a class that is used on the checkboxes
grid.tbody.on("change", ".flag", function (e)
{
// Get the record uid
var uid = grid.dataItem($(e.target).closest("tr")).uid;
// Find the current cell
var td = $(e.target).parent().parent();
// This opens the cell to edit(edit mode)
grid.editCell(td);
// This ones changes the value of the Kendo's checkbox, that is quickly shown,
// changed and then hidden again. This marks the cell as 'dirty' too.
$(td.find("input")[0]).prop("checked", $(e.target).is(":checked") ? "checked" : null).trigger("change").trigger("blur");
}
Should try something like this:
I'll set the column with the Edit button to look like this:
columns.Command(command => {command.Edit().HtmlAttributes(new { id = "btnEdit_" + "${Id}" }); }).Width(100).Hidden(true);
And have it where clicking into the first column (I have an image with a hyperlink) uses an onclick function to programmatically click the Edit button, click the checkbox, then click the Update button. Probably more "old school", but I like knowing it is following the order I would be doing if I were updating it, myself.
I pass in the object ("this"), so I can get the row and checkbox when it appears, the new status as 0 or 1 (I have some code that uses it, not really necessary for this demo, though, so I'm leaving that part out of my function for simplicity), and the ID of that item:
columns.Bound(p => p.IsActive).Title("Active").Width(100).ClientTemplate("# if (IsActive == true ) {# <a href=javascript:void(0) id=btnActive_${Id} onclick=changeCheckbox(this, '0', ${Id}) class='k-button k-button-icontext k-grid-update'><img style='border:1px solid black' id=imgActive src=../../Images/active_1.png /></a> #} else {# <a href=javascript:void(0) id=btnActive_${Id} onclick=changeCheckbox(this, '1', ${Id}) class='k-button k-button-icontext k-grid-update'><img style='border:1px solid black' id=imgActive src=../../Images/active_0.png /></a> #}#");
function changeCheckbox(obj, status, id) {
var parentTr = obj.parentNode.parentNode;
$('[id="btnEdit_' + id + '"]').click();
parentTr.childNodes[5].childNodes[0].setAttribute("id", "btnUpdate_" + id); // my Update button is in the 6th column over
parentTr.childNodes[0].childNodes[0].setAttribute("id", "chkbox_" + id);
$('[id=chkbox_' + id + ']').click().trigger("change");
$('[id=chkbox_' + id + ']').blur();
var btnUpdate = $('[id="btnUpdate_' + id + '"]');
$('[id="btnUpdate_' + id + '"]').click();
}
Code above assumes, of course, the checkbox is in the first column. Otherwise, adjust the first childNodes[0] on that chkbox setAttribute line to the column it sits in, minus one because it starts counting from zero.
I did a solution much like #DontVoteMeDown. But I have a nested grid (master / detail) so I get the parent grid from the event parameter. Also I just trigger a click-event on the checkbox.
$("#grid .k-grid-content").on("change", "input.chkbx", function (e) {
// Get the parent grid of the checkbox. This can either be the master grid or the detail grid.
var parentGrid = $(e.target).closest('div[data-role="grid"]').data("kendoGrid");
// Get the clicked cell.
var td = $(e.target).closest("td");
// Enter the cell's edit mode.
parentGrid.editCell(td);
// Find the checkbox in the cell (which now is in "edit-mode").
var checkbox = td.children("input[type=checkbox]");
// Trigger a click (which will toggle check/uncheck).
checkbox.trigger("click");
});

multiselect behavior in single select jqGrid

I have a page with a jqGrid in it. Is has to be multiselect:false because I have to allow only one row to be selected, but I also need to select multiple rows (i.e. I want to have many rows marked but only one active).
So I've created a grid whith multiselect:false and a checkbox row with formatter: 'checkbox'
I've also created a master checkbox in the collumn header (the 'name' of the collumn in the colNames is <input id="cbSelectAll" type="checkbox">)
To change all the rows at once when the header is clicked I've created the function:
$('#cbSelectAll').click(function (e) {
var valor = $(this).is(':checked');
$.each($('#grid input[type="checkbox"]'), function (idx, elm) {
var id = $(elm).closest('tr').attr('id');
var cb = $('#' + id + ' td').children().first();
$(cb).attr('checked', valor);
selectedRows[id] = valor;
});
/* other non relevant code */
});
Now that's my problem.
This function works nicelly when I try to unselect the checkbox's but when i try to select then it only works in the first time. On the subsequent clicks the checked attribute is changed but the box is not visually changed.
Instead of attr, try using prop
Please have a look at this similar issue

Adding a custom button in row in jqGrid?

I want to make a simple table that contains a custom button in a row. When the button is pushed, I want to pop up an 'alert' box. I have read some posts on this, for example:
this post
and
this other post, and I don't understand why my code is not working. The buttons are drawn, but pushing them has no effect.
I have three attempts described here.
Version 1. The button click never fires:
$(document).ready(function(){
jQuery("#simpletable").jqGrid({
datatype: "local",
colNames:['A','B','Status'],
colModel:[
{name:'A',index:'A'},
{name:'B',index:'B'},
{name:'status',index:status}
],
data:[
{'A':2,'B':100,'status':"<button onclick=\"jQuery('#simpletable').saveRow('1', function(){alert('you are in')});\" >in</button>"},
{'A':1,'B':200,'status':"<button onclick=\"jQuery('#simpletable').saveRow('2', function(){alert('you are in')});\" >in</button>"},
],
caption: "Demo of Custom Clickable Button in Row",
viewrecords:true,
editurl:'clientArray',
});
});
Html Code:
<table id="simpletable"></table>
EDIT 8/2/12 -- I've learned some things since my original post and here I describe two more attempts.
Version 2: I use onCellSelect. This works, but it would not allow me to put more than one button in a cell. Additionally, I made the code nicer by using the format option suggested by one of the comments to this post.
function status_button_maker_v2(cellvalue, options, rowObject){
return "<button class=\"ver2_statusbutton\">"+cellvalue+"</button>"
};
jQuery("#simpletablev2").jqGrid({
datatype: "local",
colNames:['A','B','Status'],
colModel:[
{name:'A',index:'A'},
{name:'B',index:'B'},
{name:'status',index:status,editable:true,formatter:status_button_maker_v2}
],
data:[
{'A':2,'B':100,'status':"In"},
{'A':1,'B':200,'status':"Out"}
],
onCellSelect:function(rowid,icol,cellcontent,e){
if (icol==2){
alert('My value in column A is: '+$("#simpletablev2").getRowData(rowid)['A']);
}else{
return true;
}
},
caption: "Demo of Custom Clickable Button in Row, ver 2",
viewrecords:true,
}); //end simpletablev2
Markup:
<style>.ver2_statusbutton { color:blue;} </style>
<h3>simple table, ver 2:</h3>
<table id="simpletablev2"></table>
Version 3: I tried to use the solution to w4ik's post, using ".on" instead of deprecated ".live". This causes the button click to fire, but I don't know how to retrieve the rowid. w4ik also struggled with this, and he posted that he worked it out, but not how he did it. I can get the last row selected, but this will always refer to the previous row selected because the button is taking priority.
I would prefer this solution if I could get it to work.
jQuery("#simpletablev3").jqGrid({
datatype: "local",
colNames:['A','B','Status'],
colModel:[
{name:'A',index:'A'},
{name:'B',index:'B'},
{name:'status',index:status,editable:true,formatter:status_button_maker_v3}
],
data:[
{'A':2,'B':100,'status':"In"},
{'A':1,'B':200,'status':"Out"}
],
caption: "Demo of Custom Clickable Button in Row, ver 3",
viewrecords:true,
onSelectRow: function(){},
gridComplete: function(){}
}); //end simpletablev3
$(".ver3_statusbutton").on(
{
click: function(){
//how to get the row id? the following does not work
//var rowid = $("#simpletablev3").attr('rowid');
//
//it also does not work to get the selected row
// this is always one click behind:
//$("#simpletablev3").trigger("reloadGrid");
rowid = $("#simpletablev3").getGridParam('selrow');
alert("button pushed! rowid = "+rowid);
}
});
Markup:
<style>.ver3_statusbutton { color:red;} </style>
<h3>simple table, ver 3:</h3>
<table id="simpletablev3"></table>
In summary, I'm struggling with the issue of getting my button to be pushed at the right time. In version 1, the row gets selected and the button never gets pushed. Version 2 does not use the "button" at all -- It just handles the cell click. Verion 3 gets the button click before the row select (wrong order).
Any help would be appreciated!
You can use action formatter here with each row and make edit and delete button as false in formatOptions like this:
formatoptions: {editbutton:false,delbutton:false}}
And follow these two demos:
http://www.ok-soft-gmbh.com/jqGrid/Admin3.htm
http://ok-soft-gmbh.com/jqGrid/TestSamle/Admin1.htm
And on click event of these custom buttons show your alert:
EDIT
var getColumnIndexByName = function (grid, columnName) {
var cm = grid.jqGrid('getGridParam', 'colModel'), i, l = cm.length;
for (i = 0; i < l; i++) {
if (cm[i].name === columnName) {
return i; // return the index
}
}
return -1;
},
function () {
var iCol = getColumnIndexByName(grid, 'act');
$(this).find(">tbody>tr.jqgrow>td:nth-child(" + (iCol + 1) + ")")
.each(function() {
$("<div>", {
title: "Custom",
mouseover: function() {
$(this).addClass('ui-state-hover');
},
mouseout: function() {
$(this).removeClass('ui-state-hover');
},
click: function(e) {
alert("'Custom' button is clicked in the rowis="+
$(e.target).closest("tr.jqgrow").attr("id") +" !");
}
}
).css({"margin-right": "5px", float: "left", cursor: "pointer"})
.addClass("ui-pg-div ui-inline-custom")
.append('<span class="ui-icon ui-icon-document"></span>')
.prependTo($(this).children("div"));
});
}
If you check this code, I'm trying to find out index value by giving column name as 'act', you can get index on any other column by giving a different column name.
var iCol = getColumnIndexByName(grid, 'Demo'); and the rest of the code will be same for you. //demo is the column name where u want to add custom button
and write your click event for this button.
Let me know if this works for you or not.

Add Remove Column Handler on jqGrid ColumnChooser

I'm using the jqGrid columnChooser, like so:
jQuery(grid).jqGrid(
'navButtonAdd',
pagerDiv,
{
caption: "Columns",
buttonicon: "ui-icon-newwin",
title: "Hide/Show Columns",
onClickButton: function () {
$(this).jqGrid('columnChooser', {
done: function (perm) {
if (perm) {
$(this).jqGrid('remapColumns', perm, true);
}
},
modal: true,
width: 400,
height: 300,
classname: 'column-chooser-select'
});
}
}
);
and was wondering if there was a way to specify an event handler on the columnChooser (using the jQuery UI Multiselect plugin that comes w/ jqGrid) that fires any time a column is either added or removed. So I guess it's a two-part question:
does the jQuery UI Multiselect support such a thing?
if so, is there a way to hook it up without altering the jqGrid source?
A bit of background on what I'm trying to achieve:
My default grid configuration hides many columns. Some of these columns are not populated from the db - they are obscure, rarely used data elements that if populated would dramatically decrease the query execution performance (multiple joins involving tables with 100 million plus records).
Should a user pick one of these columns for display i'd like to warn them that another roundtrip to the server is required and it could take a while - and give them the option to cancel the column addition.
Thanks
I think I understand your problem and find your question interesting, so I wrote the demo for you which shows how one can solve the problem.
columnChooser uses jQuery UI Multiselect plugin internally which uses jQuery UI Sortable. So I suggest to use sortreceive event of the jQuery UI Sortable to catch the information needed.
The code can be the following
$("#grid").jqGrid('navButtonAdd', '#pager', {
caption: "",
buttonicon: "ui-icon-calculator",
title: "Choose columns",
onClickButton: function () {
$(this).jqGrid('columnChooser');
$("#colchooser_" + $.jgrid.jqID(this.id) + " ul.selected")
.bind("sortreceive", function (event, ui) {
alert('column "' + ui.item.text() + '" is choosed');
});
$("#colchooser_" + $.jgrid.jqID(this.id) + " ul.available a.action")
.click(function () {
alert('column "' + $(this).parent().text() + '" is choosed');
});
}
});
See the demo here.
The code bind 'click' event on the "+" for the initial list of the columns which was in the column chooser at the initialization time of the dialog. I think it would be sufficient for you. If needed you can easy modify the code to support the 'click' on the "+" for the columns which will be removed from the left list during the work with the columnChooser.
I almost forget to mention that I used in the demo improved version of the columnChooser (see the answer), but my above suggestion works with the original version of columnChooser too.
I am using the below code in JqGrid for column chooser plug-in. when i tick the select All check box in the grid. I want to exclude particular column ( by default it should not display in my grid).
I used hidden=True property in col model. buy i want to handle these in column chooser also.
function Properties_Columnchooser() {
$('#btn_setColumns').click(function () {
jQuery('#grid-tableProperties').jqGrid('columnChooser',{
"shrinkToFit" : true,
"autowidth" : true,
done : function(perm) {
w = $(window).width();
// alert('done ' + w);
if (perm)
{
this.jqGrid("remapColumns", perm, true);
this.setGridWidth(w - 30, true);
$('.ui-search-input').show();
}
else
{
}
}
}
);
});
}

How do you handle row onclick events using Flexigrid?

My flexigrid is setup. All I need is an event that gets called when the user clicks on a row. From there, I will send the user to another page based on the data contained in that row. But I can't seem to find any examples on how to do this.
I'm looking for a clear example on how to handle row onclick events using flexigrid.
I'm also interested in any other javascript table frameworks that could be used in this situation. I've been taking a peek at DataTables and it looks like it may be a better alternative (and the project appears to be more active)
In the initial setup for the flexigrid, add the attribute process: procMe to the column model. Example:
colModel : [
{ display: 'Request', name : 'id', process: procMe }
]
and then create a callback:
function procMe( celDiv, id ) {
$( celDiv ).click( function() {
alert( id );
});
}
A better solution
Adding process to colModel didnt work for me.
colModel : [
{ display: 'Request', name : 'id', process: procMe }
]
this solution below is what I'm using:
var gridRows = $("#data-grid tbody tr");
gridRows.click(function (event) {
displaySelectedItem($(this).attr('id').substr(3));
return false; //exit
});
Flexigrid column as link
colModel: [
{
display: 'DomainName', name: 'DomainName', width: 180,
sortable: true, align: 'left',
process: function (col, id)
{
col.innerHTML = "<a href='javascript:domainEdit(" + id + ");'
id='flex_col" + id + "'>" + col.innerHTML + "</a>";
}
}]
Link Function
function domainEdit(domainID) {
alert('domainID' + domainID);
}
I think this variant little better than whoabackoff
$('.TableName').click(function(event){
$('.res').html('dbl');
alert('dbl');
});
does this help? http://www.flexigrid-asp.net/demo/updatepanel.aspx
you can have a look at it with firebug, to see where the event is hooked.
keep in mind that the flexigrid.js file is a bit different than the one from the official project.

Categories

Resources