阻止ClientTemplate在网格表单中覆盖EditorTemplate

问题描述 投票:0回答:2

我有一个带有CRUD操作的Kendo UI ASP.NET MVC网格,它作为表单的一部分提交。在下面的代码片段中,我尝试显示一个列,其中包含一个内联可编辑的组合框(绑定到用户名和ID),该组显示用户的名称,但具有用户ID的值。

正确提交表单,但显示用户ID而不是名称:

columns.ForeignKey(p => p.UserId, (System.Collections.IEnumerable)ViewBag.Users, "SystemUserId", "Name").Title("User").EditorTemplateName("ComboBoxInForm").Visible(true).ClientTemplate("#= UserId #" +
"<input type='hidden' name='Users[#= index(data) #].UserId' value='#= UserId #' />"
);

ComboBoxInForm EditorTemplate:

@model object 
@(
 Html.Kendo().ComboBoxFor(m => m)
 .BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
)

如果我删除提供表单输入标记的ClientTemplate,则显示用户的名称而不是用户ID的值,这就是我想要的。但是,我需要将其作为表单的一部分批量提交,因此我无法删除表单输入标记。

无法提交表单(无输入标记),但正确显示用户名而不是ID:

columns.ForeignKey(p => p.UserId, (System.Collections.IEnumerable)ViewBag.Users, "SystemUserId", "Name").Title("User").EditorTemplateName("ComboBoxInForm").Visible(true);

我可以使用什么解决方案来组合这两个要求,以便网格列显示名称(但具有ID值)并提供表单输入标记?

c# kendo-ui kendo-asp.net-mvc
2个回答
1
投票

首先,ClientTemplate不会覆盖EditorTemplate ...

ClientTemplate本质上是显示模板,EditorTemplate是编辑器模板。

所以,你想要的是ClientTemplate要做的是显示与UserId相关联的名称。

如果你想保持网格的方式(使用ForeignKey和隐藏字段),那么你需要添加一个“映射”功能,将组合框选择的UserId映射到相关名称。

你可以这样做:

剃刀:

.ClientTemplate("#= mapIdToName(UserId) #" +
    "<input type='hidden' name='Users[#= index(data) #].UserId' value='#= UserId #' />");

使用Javascript:

function mapIdToName(id) {
    var grid = $("#grid").getKendoGrid(),
        users = grid.options.columns[0].values,
        name;

    for (var i = 0; i < users.length; i++) {
        if (users[i].value == id) {
            name = users[i].text;
            break;
        }
    }

    return name;
}

这使用您已拥有的Id-Name数组(通过grid.options.columns.values),该数组由ForeignKey()方法创建。

替代解决方案。 。 。 。 。不过,还有其他方法可以达到你想要的效果。

一种方法是不使用ForeignKey,而是将列绑定到包含ID和Name的对象,更具体的EditorTemplate绑定到ForeignKey()所在的同一集合。这不需要映射功能,即:

剃刀:

columns.Bound(x => x.User)
    .ClientTemplate("#= User.Name #" +
    "<input type='hidden' name='Users[#= index(data) #].UserId' value='#= UserId #' />");

EditorTemplate:

@model object
@(
 Html.Kendo().ComboBoxFor(m => m)
 .DataValueField("SystemUserId")
    .DataTextField("Name")
    .BindTo((System.Collections.IEnumerable)ViewBag.Users)
)

隐藏输入法的缺点是您必须将网格限制为少量行,因为该技术只能发布单页的数据,因为第2,3页等的数据不会被渲染,因此具有表格中没有隐藏的输入要包含在帖子中。

第三种方式(这是我做事的方式)是根本不使用隐藏的输入。相反,我使用ajax调用手动发布数据,我首先将“主”表单数据(不是网格数据)序列化为对象(如果使用kendo MVVM,这非常容易),然后将修改后的网格数据与表单合并数据(使用extend)然后发布生成的组合对象。

我使用这种技术的变体来序列化网格数据:http://www.telerik.com/support/code-library/save-all-changes-with-one-request

这样做的好处是它支持更大的数据集,因为它可以使用网格分页机制(这是我喜欢这种技术的主要原因),通过提交带有所有网格/子数据的表单/标题/父数据(new / updated) / delete)在单个请求中,您可以在服务器上同时处理所有数据,从而更好地验证数据的整个“图片”,并允许更新发生在单个事务括号中。


0
投票

另一个答案from the Telerik forums

出现这种情况的原因是因为ForeignKey构建器确实提供了将与数值相关联的文本显示为内置功能。在引擎盖下,列绑定到仅包含数值的字段。为了在客户端模板中显示文本表示,应编写一些自定义逻辑。我会就如何实现这一点给出一些指导,以防这对可能面临相同困难的其他人有所帮助:

  1. input元素的值可以定义为接受实际字段值作为第一个参数而字段名称(静态文本)作为第二个参数的函数。
  2. Telerik MVC包装器呈现初始化Kendo UI小部件所需的HTML和JavaScript。每个外键列都是存储在columns.values中的键值对的数组。
  3. 这是一个函数体,其中包含一些注释,可以帮助您说明从与特定数字相关联的columns.values中查找文本的简单概念(当前字段值): function textValue(value, fieldName) { // $("#gridNameId").data("kendoGrid").options.columns contains the // columns defined in the grid's configuration // iterate through the array and check the .field value of each column to find // a column field with same name as the field name parameter (second parameter) // each column which is defined as "foreign key" does have values array. // It contains key-value pairs of each values displayed in the combo box. // return the text value associated with same value as the first first argument (value) // return text associated with the value } ClientTemplate("#= ProductID #" + "<input type='hidden' name='Products[#= index(data)#].ProductID' value='#= textValue(data.ProductID, \'ProductID\') #' />"
© www.soinside.com 2019 - 2024. All rights reserved.