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

时间:2017-04-06 17:52:37

标签: c# kendo-ui kendo-asp.net-mvc

我有一个带有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值)并提供表单输入标记?

2 个答案:

答案 0 :(得分:1)

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

ClientTemplate本质上是 display 模板,而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

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

答案 1 :(得分:0)

另一个答案from the Telerik forums

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

  1. 输入元素的值可以定义为接受实际字段值作为第一个参数而字段名称(静态文本)作为第二个参数的函数。
  2. Telerik MVC包装器呈现初始化Kendo UI小部件所需的HTML和JavaScript。每个外键列只是存储在columns.values
  3. 中的键值对的数组
  4. 这是一个功能正文,其中包含一些注释,可以帮助您说明从与特定数字相关联的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\') #' />"