Let's say I have a data like this:
[ {ID: 1, SomeForeignKeyID: 4, IsFkEnabled: true}, {ID: 2, SomeForeignKeyID: 9, IsFkEnabled: false} ]
Kendo Grid is using this data:
columns.Bound(m => m.ID); columns.ForeignKey(p => p.SomeForeignKeyID, ViewBag.ForeignKeys as IEnumerable<object>, "Value", "Name");
Here's the problem: how to make ForeignKey column editable, but only in rows, where IsFkEnabled == true? Edit mode is InCell.
k-button and/or . k-button-icontext) to set readonly or disabled. The toolbutton works, but the in-row Edit and Delete buttons may not be changed (always clickable).
Fired when the widget is bound to data from its data source. The event handler function context (available via the this keyword) will be set to the widget instance.
Description. There are situations when you would like to enable the end user to select rows or cells in the grid table, and process data from them or make calculations based on this selection. The Kendo UI grid supports selection by specifying its configuration via its selectable attribute.
Notes:
Approach #1
Use the grid's edit event and then do something like this:
$("#grid").kendoGrid({ dataSource: dataSource, height: "300px", columns: columns, editable: true, edit: function (e) { var fieldName = e.container.find("input").attr("name"); // alternative (if you don't have the name attribute in your editable): // var columnIndex = this.cellIndex(e.container); // var fieldName = this.thead.find("th").eq(columnIndex).data("field"); if (!isEditable(fieldName, e.model)) { this.closeCell(); // prevent editing } } }); /** * @returns {boolean} True if the column with the given field name is editable */ function isEditable(fieldName, model) { if (fieldName === "SomeForeignKeyID") { // condition for the field "SomeForeignKeyID" // (default to true if defining property doesn't exist) return model.hasOwnProperty("IsFkEnabled") && model.IsFkEnabled; } // additional checks, e.g. to only allow editing unsaved rows: // if (!model.isNew()) { return false; } return true; // default to editable }
Demo here (updated for Q1 2014)
To use this via the MVC fluent syntax, simply give the anonymous edit
function above a name (e.g. onEdit
):
function onEdit(e) { var fieldName = e.container.find("input").attr("name"); // alternative (if you don't have the name attribute in your editable): // var columnIndex = this.cellIndex(e.container); // var fieldName = this.thead.find("th").eq(columnIndex).data("field"); if (!isEditable(fieldName, e.model)) { this.closeCell(); // prevent editing } }
and reference it like this:
@(Html.Kendo().Grid() .Name("Grid") .Events(events => events.Edit("onEdit")) )
The disadvantage to this is that the editor gets created first before the edit event is triggered, which can sometimes have undesirable visual effects.
Approach #2
Extend the grid by overriding its editCell
method with a variation that triggers a beforeEdit
event; for that to work with grid options, you'll also need to override the init method:
var oEditCell = kendo.ui.Grid.fn.editCell; var oInit = kendo.ui.Grid.fn.init; kendo.ui.Grid = kendo.ui.Grid.extend({ init: function () { oInit.apply(this, arguments); if (typeof this.options.beforeEdit === "function") { this.bind("beforeEdit", this.options.beforeEdit.bind(this)); } }, editCell: function (cell) { var that = this, cell = $(cell), column = that.columns[that.cellIndex(cell)], model = that._modelForContainer(cell), event = { container: cell, model: model, field: column.field }; if (model && this.trigger("beforeEdit", event)) { // don't edit if prevented in beforeEdit if (event.isDefaultPrevented()) return; } oEditCell.call(this, cell); } }); kendo.ui.plugin(kendo.ui.Grid);
then use it similar to #1:
$("#grid").kendoGrid({ dataSource: dataSource, height: "300px", columns: columns, editable: true, beforeEdit: function(e) { var columnIndex = this.cellIndex(e.container); var fieldName = this.thead.find("th").eq(columnIndex).data("field"); if (!isEditable(fieldName, e.model)) { e.preventDefault(); } } });
The difference of this approach is that the editor won't get created (and focused) first. The beforeEdit
method is using the same isEditable
method from #1. See a demo for this approach here.
If you want to use this approach with MVC wrappers but don't want / can't extend GridEventBuilder, you can still bind your event handler in JavaScript (place below the grid MVC initializer):
$(function() { var grid = $("#grid").data("kendoGrid"); grid.bind("beforeEdit", onEdit.bind(grid)); });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With