All the cells in my grid are editable initially.
I want to disable cell editing for certain cells based on a value.
How can this be done?
I have the trigger setup as follows:
dataBound: function() {
$('td').each(function() {
if ($(this).children('span').data('route') == 2) {
$(this).css('background', '#CCC')
// Disable cell editing for this cell
}
})
},
All I need to know is what the line is to set the parameter for this cell to editable: false, e.g. this.something.editable = false
Related
I have a table in which I can edit and modify each cell.
I would like to highlight the cell that I modified.
At the moment I can only highlight the entire row but I don't have what I want to do.
I use createdRow to make the cells editable and get the modified row.
How can I do to highlight that modified cell?
var table = $("#deploymentMap_table").DataTable({
data: constructRaws(dataSet),//tbody
paging: false,
searching: false,
info: false,
fixedHeader: true,
scrollY: false,
scrollX: false,
responsive: false,
dom: 't', //display only the table
order: [[ 0, 'asc' ]],//order by 'service' col
columnDefs:[
{
targets:'_all',
render:function(data){
if(data == null) {return ""
} else {return data;}
}
},
{ targets: [0,1], "width" : "200px"},
],
columns: constructColumns(dataSet),//thead
dom: 'Bfrtip',
// attribute classname (background color) for services
rowCallback: function(row, data, index){
if ( data.code == 1 ) {
$('td', row).each( function ( value, index ) {
if($(this).contents().first().text()){
$(this).addClass('td_colorCD');
}
} );
}
$(row).find('td:eq(0)').css('background-color', '#7f7f7f').css('color', '#fff').css('text-align', 'left');
$(row).find('td:eq(1)').css('background-color', '#7f7f7f').css('color', '#fff').css('text-align', 'left');
$.each(row.childNodes, function(i,value){
if(value.innerText == "NoUP"){
$(value).addClass('td_colorBSF');
}
else if(value.innerText){
$(value).addClass('td_color');
}
})
},
// Make all cell editable
createdRow: function(row, data, dataIndex, cells) {
console.log(cells);
let original
row.setAttribute('contenteditable', true)
row.setAttribute('spellcheck', false)
row.addEventListener('focus', function(e) {
original = e.target.textContent
})
row.addEventListener('blur', function(e) {
if (original !== e.target.textContent) {
$('td', row).removeClass();
$('td', row).addClass('td_color_change');
const r = table.row(e.target.parentElement)
r.invalidate();
var lign = e.target.innerText;
lign = lign.split('\t');
var nRow = $('#deploymentMap_table thead tr')[0].innerText;
head = nRow.split('\n\t\n');
var newAR = mergeArrayObjects(head, lign);
console.log("newAR", newAR);
$(dataSet).each(function( index, values ) {
if(newAR.service[0].Services == values.service_name){
delete values.regions;
values.regions = newAR.region;
console.log(values);
}
})
console.log("dataset", dataSet);
}
})
}
});
I think the easiest way to handle this is to replace your rowCallback with a DataTables delegated event.
Below is a simple example which would change the color of a specific cell when you leave that cell:
Step 1) The onblur event requires the cell to have a tabindex attribute. You can add this however you wish - but here is one way, in your existing code:
$.each(row.childNodes, function(i,value){
$(value).attr('tabindex', i); // this line is new
// your existing code goes here
})
Note - this could be improved as it repeats tab indexes across rows. But it illustrates the approach.
Step 2: Add a new onblur event listener, after the end of your DataTable definition:
$('#deploymentMap_table td').on('blur', function () {
this.classList.remove("td_color");
this.classList.add("td_color_change");
} );
Step 3: The above code would need to be enhanced to include your edit-checking logic, which checks for an actual cell value change.
You can get the "before" cell values using this:
table.cell( this ).data();
And the "after" cell values using this - which gets the value from the HTML table (the DOM node), not from DataTables:
table.cell( this ).node().textContent;
The updated listener would be something like this:
$('#deploymentMap_table td').on('blur', function () {
var cellValueStart = table.cell( this ).data();
var cellValueEnd = table.cell( this ).node().textContent;
//console.log( cellValueStart );
//console.log( cellValueEnd );
if (cellValueEnd !== cellValueStart) {
table.cell( this ).data(cellValueEnd);
this.classList.remove("td_color");
this.classList.add("td_color_change");
}
} );
The table.cell( this ).data(cellValueEnd) command updates the cell in DataTables so that it matches the value you typed into the HTML cell. If you do not do this, then the data in the DataTables object (behind the scenes) will be out-of-sync with the data in the HTML table (what you see on your screen).
Warning: This approach is basic. It does not cover the case where a user may do the following:
Edit a cell from "A" to "B".
Leave the cell, so it is highlighted.
Return to the cell and edit it back from "B" to "A".
Leave the cell again.
In this case, the cell will remain highlighted.
One way around this is to capture the original state of every cell when you first load the table - and then check each edit against the value in the original data. This can be done, if needed - but is outside the scope of this question. But it also depends on what you need to do with the data, after you have finished editing it. If this is important to you, then it may be worth asking a new question for that specific problem.
I an using Ag-Grid.
I want to select column horizontal and vertical like under picture.
How to solution??
I think you would have to do this manually. You could watch for cell selection yourself, and then keep track of the selected column. Then you could use cellStyle in the column definition params to set the background color when the column is selected. You have to redraw the rows, since the cellStyle function only gets run when the rows are drawn. For example:
onCellFocused: function(params) {
if (params.column) {
selectedColumn = params.column.colDef;
params.api.redrawRows();
}
},
defaultColDef: {
cellStyle: function(params) {
if (params.colDef === selectedColumn) {
return {'background-color': '#b7e4ff'};
}
}
}
Unfortunately, it looks like redrawing the rows clears the selection, so you either have to reselect the row manually, or use a row style.
Check it out here: https://stackblitz.com/edit/ag-grid-select-column?embed=1&file=index.js
I have a tooltip in Kendo UI which I'm trying to filter cells based on their column name, because the standard td:nthchild won't work (users can move columns around). I want to engage the tooltip based on if someone hovers over MY COLUMN NAME'S CELLS. How do I accomplish that in the filter field? Or should I do it in the show function?
this.$el.kendoTooltip({
filter: "th:contains('MY COLUMN NAME')",
show: function (e) {
if (this.content.text().length > 0) {
this.content.parent().css("visibility", "visible");
}
},
hide: function(e) {
this.content.parent().css("visibility", "hidden");
},
content: function (e) {
var target = e.target;
return $(target).siblings().first().text();
}
});
Like this ?
this.$el.kendoTooltip({
filter: "thead th:contains('ColumnA')"
});
Demo
UPDATE
As you want to show the tooltip on the row cell based on the column's title, you can't use filter parameter for that, it is meant to be used to filter only the target element, which is not your case. You will need some programming there, e.g:
show: function(e) {
let index = this.target().index(), // Get hovered element's column index
columns = grid.getOptions().columns, // Get grid's columns
column = columns[index]; // Get current column
// If target TD is not under 'ColumnA', prevent tooltip from being showed
if (column.title != "ColumnA") {
this.hide();
}
}
Demo
Thanks to kendo, you can't prevent their own events, so using hide() works but the tooltips still opens blinking before it is hidden again, it's possible to catch it opening. Tried using e.preventDefault() and return false that would a reasonable way to say "cancel the widget showing" but with no luck. This was the best I could do.
I am trying to style a cell with a particular background color if the 'oldValue' and 'newValue' are not equal in the 'onCellValueChanged' handler.
var gridOptions = {
columnDefs: columnDefs,
rowData: rowData,
onCellValueChanged: function(params) {
if(params.oldValue !== params.newValue) {
params.colDef.cellStyle = function(params) {
return { backgroundColor: 'green'};
}
}
}
};
When I am editing the cell value to a new value, I don't see the style change being applied on tabbing out or clicking any other cell. Rather, I have to click back on the edited cell again and click outside after that to see the style being applied. I am not sure what is happening, can someone guide me here. I am also adding the demo
Bind it to your template
<ag-grid-angular (cellValueChanged)="onCellValueChanged($event)">
</ag-grid-angular>
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");
});