Ответ 1
Примечания:
- это решение работает только для редактирования внутри ячейки (встроенное или всплывающее редактирование требуют другого подхода)
- первый подход может привести к нежелательным визуальным эффектам (сетка прыжки) при определенных обстоятельствах; если вы это испытаете, я рекомендовать подход № 2
- подход № 2 может не работать, если вы хотите использовать обертки MVC (хотя возможно расширение Kendo.Mvc.UI.Fluent.GridEventBuilder); в этом случае вам нужно связать обработчик редактирования в JS
Подход № 1
Используйте сетку edit, а затем сделайте что-то вроде этого:
$("#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
}
Демо здесь (обновлено для Q1 2014)
Чтобы использовать это через свободный синтаксис MVC, просто выделите анонимную функцию edit
над именем (например, 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
}
}
и ссылайтесь на него следующим образом:
@(Html.Kendo().Grid()
.Name("Grid")
.Events(events => events.Edit("onEdit"))
)
Недостатком этого является то, что редактор создается первым до запуска события редактирования, что иногда может иметь нежелательные визуальные эффекты.
Подход # 2
Расширить сетку, переопределив ее метод editCell
вариацией, которая вызывает событие beforeEdit
; для этого для работы с параметрами сетки вам также необходимо переопределить метод init:
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);
то используйте его аналогично # 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();
}
}
});
Разница в этом подходе заключается в том, что редактор сначала не будет создан (и сфокусирован). Метод beforeEdit
использует тот же метод isEditable
из # 1.
См. демо для этого подхода здесь.
Если вы хотите использовать этот подход с обертками MVC, но не хотите/не можете расширять GridEventBuilder, вы все равно можете привязать обработчик событий в JavaScript (место под инициализатором MVC сетки):
$(function() {
var grid = $("#grid").data("kendoGrid");
grid.bind("beforeEdit", onEdit.bind(grid));
});