在一个页面上跨多个表单拆分一个视图模型

时间:2017-09-05 18:50:52

标签: jquery asp.net-mvc forms razor

我有一个ASP.NET MVC 5应用程序,它使用更多MVVM方法来实现MVC:它具有Entity Framework模型的“视图模型”(VM)。

我们的方案:

  • 我们有一个带有编辑视图的VM,其中包含大约7个Bootstrap选项卡。
  • 每个标签都包含自己的@using (Html.BeginForm(...)) { ... }
  • 当用户切换标签时,我们使用AJAX保存其数据(如果它有效)。

我们的挑战:

POST Edit(...)操作要求在每次AJAX调用时提交常见的隐藏表单。我们最终会有重复的隐藏字段,因为它们会针对每个表单重复:

@Html.HiddenFor(model => model.ChildVm.Application_No) 
@Html.HiddenFor(model => model.ChildVm.FormSubmitted)
// other hidden fields...

我们在设置其中一些字段时会遇到问题,其中一些字段的值对每个表单都是唯一的。因为我们通过重复ID来破坏HTML规则,所以我们必须使用一些丑陋的技巧在jQuery中设置它们的值:

// Razor helper method to fetch ASP.NET ID for control
var formSubmittedId = '@Html.ClientIdFor(m => m.ChildVm.FormSubmitted)';

// Tab change handler
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
    var form = $(e.relatedTarget).attr('href');
    var formId = $(e.relatedTarget).attr('href').replace('#', '');
    var previousTab = $(form + '-form');
    $(previousTab).find('#' + formSubmittedId).val(formId);
    //....
});

以上作品但很难看。如何在同一个CSHTML上的多个表单中包含来自同一视图模型的表单字段而没有重复的ID?如果我给字段提供不同的ID,那么是否会破坏Edit的POST操作,该操作使用客户端的ID将它们与视图模型服务器端的各自属性相匹配?

感谢。

1 个答案:

答案 0 :(得分:1)

表单回发其成功表单控件的名称/值对,而不是其id属性的值。 id属性的唯一目的是在javascript / jquery和css选择器中使用。

要防止无效的html(重复的id属性),您只需使用(不需要丑陋的脚本)删除该属性

@Html.HiddenFor(model => model.ChildVm.Application_No, new { id = "" }) 

但是一般情况下,您应该避免在视图中隐藏输入(与记录ID相关的输入除外),尽管最好将该值作为路径值添加到您的视图中。如果您需要POST方法中其他隐藏输入的值,那么您应该根据ID再次获取记录。

如果由于某种原因,您确实需要在每个ajax帖子中回发所有这些附加值,更好的解决方案是将这些输入仅包含在单独的<form>元素中并使用{{1}组合值的方法,例如

.serialize()

然后在脚本中发布表单

<form id="hiddeninputs">
    @Html.HiddenFor(model => model.ChildVm.Application_No)
    .... // other hidden inputs
<form>
@using (Html.BeginForm(....))
{
    .... // form controls for 1st tab
}
@using (Html.BeginForm(....))
{
    .... // form controls for 2nd tab
}

您甚至可以完全删除隐藏的输入,并构建一个要回发的对象

$('form').submit(function() {
    var formdata = $(this).serialize() + '&' + $('#hiddeninputs').serialize;
    $.ajax({
        ....
        data: formdata,
        ....
    });
    return false; // cancel the default submit

并使用

var hiddeninputs = {
    'ChildVm.Application_No': '@Model.ChildVm.Application_No',
    ....
}