【问题标题】:CheckBoxFor Html helper's hidden field issue with serializeArrayCheckBoxFor Html 助手的隐藏字段问题与 serializeArray
【发布时间】:2015-08-07 11:22:53
【问题描述】:

我有一个这样的表格。

<form id="myForm">
    <div>
        <ul>
            <li>
                @Html.DropDownListFor(m => m.SelectedVal, new SelectList(Model.ValLst, "Value", "Name"))
            </li>
            <li>
                @Html.TextBoxFor(m => m.Id)
            </li>
            <li>
                @Html.CheckBoxFor(m => m.IsPaid, new { @Id = "IsPaid"})
            </li>
        </ul>           
    </div>
</form>

我必须按如下方式序列化此表单,并且我正在对序列化数组进行操作

values = $('#myForm').serializeArray();

0: Object
name: "SelectedVal"
value: "BMV"

1: Object
name: "Id"
value: "123"

2: Object
name: "IsPaid"
value: "true"

3: Object
name: "IsPaid"
value: "false"

我遇到了 CheckBoxFor 助手的问题。因为,它正在创建一个值为 false 的隐藏字段,并且隐藏字段和复选框都具有相同的 id。所以复选框的模型值总是假的,即使它被选中。即在对序列化数组进行操作时,隐藏字段值会覆盖复选框值。

所以我想在序列化时忽略隐藏字段。喜欢:

values = $('#myForm').find("input[type != 'hidden']").serializeArray();

0: Object
name: "Id"
value: "123"

1: Object
name: "IsPaid"
value: "true"

但是,它不起作用,因为我没有得到下拉值。所以,想了想,DropDownListFor 也使用了隐藏字段。任何建议,如何将复选框的正确值发送到控制器。诸如忽略复选框或任何其他 html 帮助器之后的立即隐藏字段或强制在复选框之前呈现隐藏字段。

【问题讨论】:

  • 使用.serialize()(不是.serializeArray())。如果您的控制器方法有一个参数是视图中使用的模型,那么您的模型将被正确绑定(并且DropDownListFor() 不会生成隐藏字段,并且与复选框关联的隐藏输入没有id!)
  • 我需要遍历序列化的表单并对其进行操作。所以要使用 each() 我正在使用序列化数组。
  • 也许你应该展示你的代码:)
  • 您的编辑没有显示您的脚本。
  • 我的意思是显示你在哪里执行 $.each() 的脚本 :) 并且 DropDownListFor() 不会生成 &lt;input&gt; - 它会生成 &lt;select&gt; 并且它不是隐藏的(尽管如果你使用一个 jquery 插件,插件可能会隐藏它)。正确的选择器是 find('input, select').not(':hidden') 但这不会解决您的问题(尽管您可能会想)

标签: jquery asp.net-mvc asp.net-mvc-5 html-helper


【解决方案1】:

您需要使用$('#myForm').serialize();,而不是$('#myForm').serializeArray();

.serializeArray() 正在回发IsPaid=[true, false],即不能绑定到boolean 属性的值数组(它与覆盖复选框的隐藏输入无关),其中.serialize() 将发布IsPaid=true&amp;IsPaid=false 将正确绑定到您的模型(DefaulModelBinder 读取第一个值 (true) 并忽略任何后续具有相同名称的名称/值对。

旁注:@Html.DropDownListFor() 不会生成隐藏输入。 @Html.CheckBoxFor() 生成的隐藏输入没有id 属性,new { @Id = "IsPaid"} 毫无意义。助手已经生成了id

【讨论】:

  • 你是 100% 正确的。但是,我的要求完全不同。它已经设计好了。我只是添加一个部分视图。一个视图有几个局部视图。每个局部视图都是一种形式。这些表单的 ID 对应于用于绑定主视图的 ViewModel 的属性。所以他们形成了对象的对象。每个局部视图的内容都在一个唯一的对象中。最后,对象的 Object 被字符串化并发送到 ajax 上的操作。希望,我现在明白了
  • 一点也不 :) (它仍然是一个糟糕的设计)。但如果您真的想这样做,请使用var values = $('#myForm').serializeArray(); $.each(values, function () { // manipulate your data }); var data = $.param(values);$.params() 函数正确序列化数组,因此您现在可以使用$.post(url, data, function(..) { ... });(或$.ajax({ data: data, ....}),它将被DefaultModelBinder正确绑定
【解决方案2】:

我错过了选择元素。应该是

values = $('#myForm').find('input, select').not(':hidden').serializeArray();

【讨论】:

  • 你不明白我的评论“这不会解决你的问题(尽管你可能会想)”
  • @StephenMuecke 它解决了我的问题。我无法完全解释我的要求。但是,它正在按预期进行。谢谢。
  • 不,不会。很抱歉很苛刻,但很明显你有很多关于 MVC 的知识要学习。 CheckboxFor() 方法生成隐藏输入是有充分理由的 - 因此,当未选中该复选框时,它会回发 false。假设您有一个 bool 属性,默认值为 true(在构造函数中设置)。现在用户取消选中它 - 因此在您的情况下,您不发布任何内容(未选中的复选框不会回发),因此该值设置为 true,尽管用户认为他们刚刚将其设置为 false。你只是继续做越来越多的黑客来克服一个糟糕的设计。
  • 我想,我会从控制器发送默认值 false 并且如果我忽略序列化中的隐藏字段不会有问题。但是,它不起作用。
  • 你的问题在于你的设计。我不知道您的json[this.name] = .. 在做什么,但是如果您试图操纵您发布的值的名称,那么您的做法是错误的。您刚刚编写 hack(我看到您刚刚接受了另一个)来做 MVC 开箱即用的事情。附带说明一下,CheckBoxFor() 生成的隐藏输入确实 not 具有 id 属性,并且您接受的代码不起作用。
【解决方案3】:

复选框的值始终为真,隐藏字段的值始终为假。但是,对于选中的复选框,它的父跨度包含一个“选中”类。因此,在序列化之前,我们可以将所需的值保留在隐藏字段中。现在,让它覆盖。如果父跨度有“已检查”类,则在相应的隐藏字段中保持“真”,否则为假。

        // traverse through all the checkboxes, check class of it's parent span

        $("input[type='checkbox']").each(function () {
            // id of hidden field is same as that of the check box
            var hdnFldId = "input[type='hidden']#" + $(this).attr('id');
            if ($(this).parent().hasClass('checked'))
            {
                $(hdnFldId).val(true);
            }
            else {
                $(hdnFldId).val(false);
            }
        });
        values = $('#myForm').serializeArray();

【讨论】:

    猜你喜欢
    • 2015-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-08
    • 1970-01-01
    • 1970-01-01
    • 2011-04-19
    相关资源
    最近更新 更多