dojo dgrid multiple cells edit - javascript

Is it possible to edit multiple cells of the dgrid at the same time ?
I know that we can edit a single cell at a time by double/single clicking that cell and update it. And on the onBlur of that cell, the edited data gets updated for that cell.
But my requirement is:
click edit-link/edit-button for each row, which will display editors for the all the editable cells of that row,
update/edit the cells,
then click the save button(which will be next to the edit button) for that same row,
on clicking the Save link/icon , the edited cell's value should get saved to the store/server.
Below are some of the columns of the Grid.
// one of the editable columns others are also similar to this one..
editor({
label:"Outcome",
field:"outcome",
sortable: false,
editorArgs: {
options:[
{value: "1", label: "Opt1"},
{value: "2", label: "Opt2"},
{value: "3", label: "Opt3"},
]
},
renderCell: function(row, value, td, options){
put(td, "div", outcomeOptionsMap[value] || '');
}
}, Select, "dblclick" ),
// last column
{label:"Actions", field:"actions",sortable: false,
renderCell: function(row, value, td, options){
newValue = "<a href=\"#\" title=\"Edit\" onclick='editEntireRow(testgrid,event);'><img src='../static/images/edit.gif'/></a>";
newValue = "<a href=\"#\" title=\"Save\" onclick='saveRow(testgrid,event);'><img src='../static/images/edit.gif'/></a>";
newValue += " <a href=\"#\" title=\"Delete\" onclick='testgrid.store.remove("+row.id+");'><img src='../static/images/delete_icon.png'/></a>";
td.innerHTML = newValue;
}
BTW, I am using the dojo.store.JsonRest as store .
Grid Declaration
var MyGrid = declare([Grid, Selection, Keyboard]);
window.testgrid = new MyGrid(
{
store : Observable(Cache(jsonRest, Memory())),
selectionMode : "none",
getBeforePut: false,
columns: getColumns,
allowSelectAll: true,
minRowsPerPage: 5,
maxRowsPerPage: 20,
}, "gridContainer");
currently I am trying something like this, but not working...
function editEntireRow(grid,event){
// cols 3,5,7,8 steps to the left of the Action column are editable
grid.edit(grid.left(grid.cell(event),3));
grid.edit(grid.left(grid.cell(event),5));
grid.edit(grid.left(grid.cell(event),7));
//grid.edit(grid.left(grid.cell(event),8));
}

Related

jqgrid Allow only one cell per row to be selected. Not working after a sort is performed

My goal is to be able to highlight a cell when clicked and remove highlight when clicked again. Each row can have only one cell highlighted. I have attempted to get it to work but whenever the grid is sorted, my target functionality doesn't seem to work anymore. Any help or suggestion will be highly appreciated.
Here is the demo JSFiddle
I believe the problem lies around here...
loadComplete: function () {
var gridParams = jQuery(this).jqGrid("getGridParam");
var selectedCells = gridParams.mySelection;
var rowId, columnName, cellValue;
if (selectedCells.length > 0) {
for (var i = 0; i < selectedCells.length; i++) {
rowId = selectedCells[i].rowId;
columnName = selectedCells[i].columnName;
cellValue = selectedCells[i].cellValue;
jQuery(this).setCell(rowId, columnName, cellValue, 'ui-state-highlight', '', true);
jQuery(this).jqGrid('getLocalRow', rowId).columnName = cellValue;
}
}
},
Your question (and your issue) isn't easy. Thus I'm answering with delay.
First of all, you have to include some unique id values in your data to be sure that rowids will stay unchanged after sorting the data. As the values you can use any unique values, for example, 1, 2, ..., 5 or 10, 20, ... 50 or any other values. I changed the input data from your demo to the following:
var data = [
{ id: 10, win: 50, draw: 20, defeat: 30 },
{ id: 20, win: 40, draw: 10, defeat: 50 },
{ id: 30, win: 30, draw: 50, defeat: 20 },
{ id: 40, win: 20, draw: 60, defeat: 20 },
{ id: 50, win: 70, draw: 20, defeat: 10 }
];
The next problem: the information, which you saves in mySelection parameter. Your current implementation saves array of objects with the following properties: rowId, cellId, columnName, cellValue and selectedCell, where selectedCell is DOM element which represent selected <td> element. I find not good saving selectedCell because the content of grid will be rebuild after sorting and the selectedCell will point to DOM element removed from HTML page. Additionally, you searing elements in mySelection by rowid (see the code of returnExistingRowSelectedCells function). The code could be reduced to one line if you would modify the information saved in mySelection to the map: column name by rowid. For example, if you select 3 cells in the grid like on the picture below
then the current implementation will hold mySelection like
[{
"rowId": "20",
"selectedCell": {...},
"cellId": "20_draw",
"columnName": "draw",
"cellValue": 10
}, {
"rowId": "40",
"selectedCell": {...},
"cellId": "40_win",
"columnName": "win",
"cellValue": 20
}, {
"rowId": "30",
"selectedCell": {...},
"cellId": "30_defeat",
"columnName": "defeat",
"cellValue": 20
}]
(in your original demo rowId was the values like "jqg4", "jqg2" and "jqg3"). I suggest to replace the array to the object like
{
"20": "draw",
"40": "win",
"30": "defeat"
}
I uses column names instead of column indexes to be sure that one don't need to update the data if the order of columns will be changed by drag & drop column headers (one need to add to the demo jquery-ui.min.js of cause to make the option sortable: true, which you use workable).
The last remark is about addressing of cells by column name. Free jqGrid hold internal parameter iColByName, which allows to get column index by column name (gridParams.iColByName[colName]). Additionally the method getGridRowById can be used to get <tr> by rowid and then one van use $.jgrid.getCell to get jQuery wrapper to the cell (<td>) by column index:
var tr = $(this).jqGrid("getGridRowById", rowid);
var $td = $jgrid.getCell.call(this, tr, iCol); // mostly $(tr.cells[iCol]);
In the way you need just hold rowid and the column name and the get $td having the information. You can then use $td.addClass("ui-state-highlight") or $td.removeClass("ui-state-highlight") for selection/deselection the cell.
The modified code could be like the following
mySelection: {},
loadComplete: function() {
var $this = jQuery(this), gridParams = $this.jqGrid("getGridParam"),
selectedCells = gridParams.mySelection, rowId, tr, iCol, $td;
for (rowId in selectedCells) {
if (selectedCells.hasOwnProperty(rowId)) {
tr = $this.jqGrid("getGridRowById", rowId);
iCol = gridParams.iColByName[selectedCells[rowId]];
$td = jQuery.jgrid.getCell.call(this, tr, iCol);
$td.addClass("ui-state-highlight");
}
}
},
onCellSelect: function(rowId, iCol, cellContent, element) {
var $this = jQuery(this),
gridParams = $this.jqGrid("getGridParam"),
selectedCells = gridParams.mySelection;
if (selectedCells[rowId]) {
// some sell is already selected in the row
var tr = $this.jqGrid("getGridRowById", rowId),
iColSelected = gridParams.iColByName[selectedCells[rowId]],
$tdSelected = jQuery.jgrid.getCell.call(this, tr, iColSelected);
$tdSelected.removeClass("ui-state-highlight");
if (gridParams.iColByName[selectedCells[rowId]] === iCol) {
// the current cell will be unselected
delete selectedCells[rowId];
return;
}
}
// select the cell
jQuery(element.target).closest("td").addClass("ui-state-highlight");
// update column name in mySelection
selectedCells[rowId] = gridParams.colModel[iCol].name;
},
beforeSelectRow: function(rowId, element) {
return false;
},
See the modified demo https://jsfiddle.net/OlegKi/hwondp71/37/.

Hiding Columns in the Columns of the Column menu option based on condition

I am using Kendo Column Menu option for kendo grid.I want that while hiding/showing the columns through the third option i.e Column I want to hide the Menus if the title of that column is blank.
Here I want to Hide the RefValue4 and RefValue5 since it corresponding values are coming null from the database.so there is no need of showing these.
I am doing this way:
if (grid.dataSource.data()[0].RefName4==null) {
grid.hideColumn(18);
}
but not able to achieve the result.
Is enough checking the content of the first row of the grid (as you propose in your code sample(? If so, you can define a dataBound handler that hides columns as:
dataBound : function (e) {
// Get reference to the grid
var grid = e.sender;
// Get reference to received data
var data = e.sender.dataSource.data();
// Check that we actually received any data
if (data.length > 0) {
// Iterate on columns hiding those that in the first row have no data
$.each(grid.options.columns, function (idx, elem) {
if (!data[0][elem.field]) {
grid.hideColumn(idx);
}
});
}
}
This runs anytime that you receive data from the server but as I said, only checks for the content of the first but you can easily modify for checking all. What this does not implement is hiding the column title from the menu.
See a running example here: http://jsfiddle.net/OnaBai/XNcmt/67/
EDIT: If you need that columns with no data are not displayed but also do not show up in the menu, you need to configure columns in the grid without those columns. You can do it in runtime once the data is received doing something like:
// Fetch data from the DataSource
ds.fetch(function (d) {
// By default, no column in the grid
var columns = [];
// List of available column definitions
var definitions = [
{ field: "Id", hidden: true },
{ field: "FirstName", title: "First Name" },
{ field: "LastName", title: "Last Name" },
{ field: "City" },
{ field: "Position" }
];
// For each column in the definition check if there is data
$.each(definitions, function(idx, elem) {
if(d.items[0][elem.field]) {
// If there is data then copy the definition to columns
columns.push(elem);
}
});
// Use received data plus the columns definition computed
$("#grid").kendoGrid({
dataSource: d.items,
editable : false,
pageable : true,
columnMenu: true,
columns : columns
}).data("kendoGrid");
});
Where ds is the DataSource definition.
See it here : http://jsfiddle.net/OnaBai/XNcmt/69/

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.

How to get gridPanel cell value? ExtJs

I have a gridPanel with ColumnModel. One of this columns is ActionColumn with buttons. And i want by click a button get a cell value from cell in same row with this button? How to do this?
My ActionColumn
{
xtype: 'actioncolumn',
width: 50,
items: [{
icon : url_servlet+'externals/gxp/src/theme/img/pencil.png',
tooltip: 'Редактировать участок',
handler: function(grid, rowIndex, colIndex) {
alert("DAMACIA!!!!");
}
You have all you need in handler params
handler: function(grid, rowIndex, colIndex) {
var row = grid.getStore().getAt(rowIndex);
console.log(row);
}
The code above will give you the row, so you just need to select desired cell.
If you enforce selection before clicking actioncolumn you can also use code below. But be aware by default clicking on actioncolumn doesn't fire selection, so while clicking actioncolumn an entirely different row can be selected or even no column can be selected at all.
grid.getSelectionModel().getSelection()

how to change the content of a header cell in dataTables?

I'm using the dataTables plugin
On my sortable columns I want to replace the column text with a button.
However doing this:
$( oSettings.aoColumns[i].nTh).text();
I can retrieve the text of the respective column, BUT
$( oSettings.aoColumns[i].nTh).text("some text");
$( oSettings.aoColumns[i].nTh).html("<a href='#'>some button</a>");
Does not do anything.
Can somebody tell me why I can retrieve info from a cell but not edit it's content? Not necessarily a dataTables question, but maybe someone has run into something similar.
Thanks for help!
EDIT: This is the solution:
Inside your table call specify, which columns should be sortable = these get a .jqmSorter class
"aoColumns": [
/* Select */ {"bSortable": false },
/* Type */ {"sClass": "jqmSorter"},
/* From */ {"bSortable": false },
/* Status */ {"bSortable": false },
],
Then call the fnHeaderCallback in which I'm replacing the header cell content with a JQM button:
"fnHeaderCallback": function( nHead ) {
$(nHead).closest('thead').find('.jqmSorter').each( function () {
var sortTitle = $(this).text(),
sortButton =
$( document.createElement( "a" ) ).buttonMarkup({
shadow: false,
corners: false,
theme: 'a',
iconpos: "right",
icon: "ui-icon-radio-off"
})
sortButton.find('.ui-btn-text').text(sortTitle);
$(this).html( sortButton )
sortButton.addClass("colHighTrigger");
});
}
You can do it this way:
While defining table columns (define if you not doing it already), and use the sClass attribute of the table column definition (which is in JSON).
After this, that class will be applied to the table column.
After this, use the callback function of datatables : fnRowCallback
and in this, set the html as
$(nRow, '.your_class').html('Your HTML Values');
This will be called when each row of the table is rendered.
If you don't want it to do on each row, you can control that with an if-condition.
Use fnRender in your aoColumns settings, use it to return HTML code for that specific cell, drop downs, checkboxes, anything you want will work there.
"aoColumns": [
/*Col 1*/
{
"mData": "RowID",
"bSortable": false,
"sClass": "jqmSorter",
"fnRender": function(obj){
return "<input id='" + obj.aData.RowID + "' type='button' value='myval'/>"
}
},
/*Col 2*/
{
"bSortable": false,
"sClass": "jqmSorter",
"fnRender": function(obj){
return "<input id='" + obj.aData.RowID + "' type='button' value='myval'/>"
}
}
]

Categories

Resources