tablas - modificar tabla con javascript
Hacer que la celda sea de solo lectura en la rejilla Kendo si se cumple la condiciĆ³n (5)
La forma más simple es usar el evento dataBound para aplicar condicionalmente una de las clases CSS especiales a las celdas que la cuadrícula ignora para editarlas:
dataBound: function(e) { var colIndex = 1; var rows = this.table.find("tr:not(.k-grouping-row)"); for (var i = 0; i < rows.length; i++) { var row = rows[i]; var model = this.dataItem(row); if (!model.Discontinued) { var cell = $($(row).find("td")[colIndex]); cell.addClass("k-group-cell"); } } },
Digamos que tengo una información como esta:
[
{ID: 1, SomeForeignKeyID: 4, IsFkEnabled: true},
{ID: 2, SomeForeignKeyID: 9, IsFkEnabled: false}
]
Kendo Grid está usando esta información:
columns.Bound(m => m.ID);
columns.ForeignKey(p => p.SomeForeignKeyID, ViewBag.ForeignKeys as IEnumerable<object>, "Value", "Name");
Aquí está el problema: cómo hacer que la columna ForeignKey sea editable, pero solo en filas, donde IsFkEnabled == true? El modo de edición es InCell.
Ninguno de estos enfoques funcionó para mí. Una implementación muy simple se parece a esto
edit: function (e) {
e.container.find("input[name=''Name'']").each(function () { $(this).attr("disabled", "disabled") });
}
Donde la edición es parte de la declaración de la red kendo y Name es el nombre real del campo.
Otro enfoque es usar su propia función de "editor" para la definición de columna que proporciona un elemento de entrada o un div simple dependiendo de su condición.
Por favor intente con el siguiente fragmento de código.
VER
<script type="text/javascript">
function errorHandler(e) {
if (e.errors) {
var message = "Errors:/n";
$.each(e.errors, function (key, value) {
if (''errors'' in value) {
$.each(value.errors, function () {
message += this + "/n";
});
}
});
alert(message);
}
}
function onGridEdit(arg) {
if (arg.container.find("input[name=IsFkEnabled]").length > 0) {
arg.container.find("input[name=IsFkEnabled]").click(function () {
if ($(this).is(":checked") == false) {
}
else {
arg.model.IsFkEnabled = true;
$("#Grid").data("kendoGrid").closeCell(arg.container);
$("#Grid").data("kendoGrid").editCell(arg.container.next());
}
});
}
if (arg.container.find("input[name=FID]").length > 0) {
if (arg.model.IsFkEnabled == false) {
$("#Grid").data("kendoGrid").closeCell(arg.container)
}
}
}
</script>
<div>
@(Html.Kendo().Grid<MvcApplication1.Models.TestModels>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(p => p.ID);
columns.Bound(p => p.Name);
columns.Bound(p => p.IsFkEnabled);
columns.ForeignKey(p => p.FID, (System.Collections.IEnumerable)ViewData["TestList"], "Value", "Text");
})
.ToolBar(toolBar => toolBar.Save())
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Pageable()
.Sortable()
.Scrollable()
.Filterable()
.Events(e => e.Edit("onGridEdit"))
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.ServerOperation(false)
.Events(events => events.Error("errorHandler"))
.Model(model =>
{
model.Id(p => p.ID);
model.Field(p => p.ID).Editable(false);
})
.Read(read => read.Action("ForeignKeyColumn_Read", "Home"))
.Update(update => update.Action("ForeignKeyColumn_Update", "Home"))
)
)
</div>
MODELO
namespace MvcApplication1.Models
{
public class TestModels
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsFkEnabled { get; set; }
public int FID { get; set; }
}
}
CONTROLADOR
public class HomeController : Controller
{
public ActionResult Index()
{
List<SelectListItem> items = new List<SelectListItem>();
for (int i = 1; i < 6; i++)
{
SelectListItem item = new SelectListItem();
item.Text = "text" + i.ToString();
item.Value = i.ToString();
items.Add(item);
}
ViewData["TestList"] = items;
return View();
}
public ActionResult ForeignKeyColumn_Read([DataSourceRequest] DataSourceRequest request)
{
List<TestModels> models = new List<TestModels>();
for (int i = 1; i < 6; i++)
{
TestModels model = new TestModels();
model.ID = i;
model.Name = "Name" + i;
if (i % 2 == 0)
{
model.IsFkEnabled = true;
}
model.FID = i;
models.Add(model);
}
return Json(models.ToDataSourceResult(request));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ForeignKeyColumn_Update([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<TestModels> tests)
{
if (tests != null && ModelState.IsValid)
{
// Save/Update logic comes here
}
return Json(ModelState.ToDataSourceResult());
}
}
Si quieres descargar una demo, haz clic here .
Notas:
- esta solución funciona solo para la edición interna (la edición en línea o emergente requiere un enfoque diferente)
- el primer enfoque puede provocar efectos visuales no deseados (salto de cuadrícula) bajo ciertas circunstancias; si experimentas eso, recomiendo el enfoque n. ° 2
- el enfoque n.º 2 puede no funcionar si desea utilizar los contenedores MVC (aunque es posible ampliar Kendo.Mvc.UI.Fluent.GridEventBuilder); en ese caso, deberá vincular el controlador de edición en JS
Enfoque # 1
Use el evento de edit la grilla y luego haga algo como esto:
$("#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
}
Demostración aquí ( actualizado para Q1 2014 )
Para usar esto a través de la sintaxis fluida de MVC, simplemente dé la función de edit
anónima sobre un nombre (por ejemplo, en 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
}
}
y hacer referencia de esta manera:
@(Html.Kendo().Grid()
.Name("Grid")
.Events(events => events.Edit("onEdit"))
)
La desventaja de esto es que el editor se crea primero antes de que se desencadene el evento de edición, que a veces puede tener efectos visuales no deseados.
Enfoque # 2
Extienda la grilla anulando su método editCell
con una variación que desencadena un evento beforeEdit
; para que eso funcione con las opciones de cuadrícula, también tendrás que anular el método 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);
luego utilícelo de manera similar a # 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();
}
}
});
La diferencia de este enfoque es que el editor no se creará (y enfocará) primero. El método beforeEdit
está utilizando el mismo método isEditable
desde # 1. Vea una demostración de este enfoque aquí .
Si desea utilizar este enfoque con envoltorios MVC pero no desea / no puede extender GridEventBuilder, puede enlazar su controlador de eventos en JavaScript (coloque debajo del inicializador MVC de la grilla):
$(function() {
var grid = $("#grid").data("kendoGrid");
grid.bind("beforeEdit", onEdit.bind(grid));
});