代码之家  ›  专栏  ›  技术社区  ›  Sascha

选中EditorForMVC视图上的所有复选框

  •  1
  • Sascha  · 技术社区  · 6 年前

    我当前的视图正在显示员工列表。显示的所有行和列都是模型绑定的。

    请参见下面的我的视图代码:

    @using System.Linq
    @using DN_.Extensions
    @model DN_.Models.NotificationsModel
    <script src="~/Scripts/jquery-3.3.1.min.js"></script>
    
    <script type="text/javascript" language="javascript">
        $(function () {
            $("#checkAll").click(function () {
                $("input[id='cb_Notify']").prop("checked", this.checked).change();
                var count = $("input[name='cb_Notify']:checked").length;
            })
    
            $("input[id='cb_Notify']").click(function () {
                if ($("input[name='cb_Notify']:checked").length == $("input[id='cb_Notify']").length) {
                    $("#checkAll").prop("checked", "checked").change();
                }
                else {
                    $("#checkAll").removeProp("checked").change();
                }
            })
        })
    </script>
    
    @{
        ViewBag.Title = "Link Employees";
    }
    
    <h2>Link Employees</h2>
    
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
        <input id="btn_Save" type="submit" value="Save" class="btn btn-default" />
    
        @Html.ActionLink("Back to List", "Index")
        <p>
            Select All <input type="checkbox" id="checkAll" />
            Select All On Premise <input type="checkbox" id="checkAllOnPremise" />
            Select All Full Timers<input type="checkbox" id="checkAllFullTimers" />
        </p>
        <table class="table">
            <tr>
                <th align=center>Notify?</th>
                <th align=center>Employee Name</th>
                <th align=center>Is On Premise</th>
                <th align=center>Is Full Time</th>
                <th align=center>Notified On</th>
            </tr>
    
            @for (var i = 0; i < Model.EmployeeNotification.Count; i++)
            {
    
                <tr>
                    <td>
                        @*Do not allow editing of the Notify field for employees who have been sent the notification already*@
                        @if (Model.EmployeeNotification[i].NotifiedOn >= DateTime.Parse("2000-01-01 12:00:00 AM"))
                        {
                            @Html.DisplayFor(modelItem => Model.EmployeeNotification[i].Notify)
                        }
                        else
                        {
                            @*Hidden items for the post back information*@
                            @Html.HiddenFor(modelItem => Model.EmployeeNotification[i].NotificationID)
                            @Html.HiddenFor(modelItem => Model.EmployeeNotification[i].EmployeeID)
                            @Html.HiddenFor(modelItem => Model.EmployeeNotification[i].EmployeeName)
    
                            @*BELOW 3 LINES ARE THE PROBLEM DESCRIBED*@
                            @Html.EditorFor(modelItem => Model.EmployeeNotification[i].Notify)
                            @Html.CheckBoxFor(modelItem => Model.EmployeeNotification[i].Notify)
                            @*This checkbox below works with the "Select All" option, but data is not posted back.*@
                            @Html.CheckBox("cb_Notify", Model.EmployeeNotification[i].Notify)
                        }
                    </td>
                    <td>
                        @Model.EmployeeNotification[i].EmployeeName
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => Model.EmployeeNotification[i].IsOnPremise)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => Model.EmployeeNotification[i].IsFullTime)
                    </td>
                    <td>
                        @if (Model.EmployeeNotification[i].NotifiedOn >= DateTime.Parse("2000-01-01 12:00:00 AM"))
                        {
                            @Html.RenderDate(Model.EmployeeNotification[i].NotifiedOn, "dd MMM yyyy")
                        }
                    </td>
                </tr>
            }
        </table>
    }
    

    我的问题如下: 我可以使用第一个Notify Checkbox代码行(即使用EditorFor和CheckBoxFor选项)手动选择所有Notify复选框,并在post back事件中保存数据。

    对我来说,named CheckBox选项与Select All框的预期效果一样,但是我无法将数据返回到post事件处理程序。所选Notify列的模型数据返回为null。

    <td>
        <!--Required, hidden data for post back event handler:-->
        <input name="EmployeeNotification[3].NotificationID" id="EmployeeNotification_3__NotificationID" type="hidden" value="6" data-val-number="The field NotificationID must be a number." data-val="true">
        <input name="EmployeeNotification[3].EmployeeID" id="EmployeeNotification_3__EmployeeID" type="hidden" value="27" data-val-number="The field EmployeeID must be a number." data-val="true">
        <input name="EmployeeNotification[3].EmployeeName" id="EmployeeNotification_3__EmployeeName" type="hidden" value="Charlie">
        <!--@Html.EditorFor element-->
        <input name="EmployeeNotification[3].Notify" id="EmployeeNotification_3__Notify" type="checkbox" value="true" data-val="true" data-val-required="The Notify field is required.">
        <input name="EmployeeNotification[3].Notify" type="hidden" value="false">
        <!--@Html.CheckBoxFor element-->
        <input name="EmployeeNotification[3].Notify" id="EmployeeNotification_3__Notify" type="checkbox" value="true">
        <input name="EmployeeNotification[3].Notify" type="hidden" value="false">
        <!--@Html.CheckBox element-->
        <input name="cb_Notify" id="cb_Notify" type="checkbox" value="true">
        <input name="cb_Notify" type="hidden" value="false">
    </td>
    

    所以我要么需要选中所有复选框来处理@Html.EditorFor或者@Html.CheckBoxFor选项或我需要获取@Html.CheckBox文件在post事件处理程序中。

    我无法在“选择或选中所有”复选框中的其他类似问题中获得所需的答案,因为它们似乎使用其他编码语言。请帮忙。

    请注意:

    简单地说,我们的目的是在最后只保留一个可选的Notify复选框。会有用的那个。不是所有的三个。由于测试和调试不成功,我现在只显示了它们。

    2 回复  |  直到 6 年前
        1
  •  3
  •   user3559349 user3559349    6 年前

    因为你的 name (和 id Attribute Ends With Selector (例如 $('input[type="checkbox"][name$="Notify"]') ),但仅为复选框使用类名会更容易。

    @Html.CheckBoxFor(m => m.EmployeeNotification[i].Notify, new { @class = "notify" })
    

    然后你就可以

    // cache for performance
    var checkboxes = $('.notify');
    var total = checkboxes.length;
    var checkall = $('#checkAll');
    
    checkall.change(function() {
        checkboxes.prop('checked', $(this).is(':checked'));
    })
    
    checkboxes.change(function() {
        var count = checkboxes.filter(':checked').length;
      checkall.prop('checked', (count == total));
    })
    

    但是,您的代码还有另一个问题。默认情况下 DefaultModelBinder @if (Model.EmployeeNotification[i].NotifiedOn >= DateTime.Parse("2000-01-01 12:00:00 AM")) EmployeeNotification 财产将 null 就业通知 绑定非零/非连续索引器

    @if (Model.EmployeeNotification[i].NotifiedOn >= DateTime.Parse("2000-01-01 12:00:00 AM"))
    {
        @Html.DisplayFor(m => m.EmployeeNotification[i].Notify)
    }
    else
    {
        @Html.HiddenFor(m => m.EmployeeNotification[i].NotificationID)
        @Html.HiddenFor(m => m.EmployeeNotification[i].EmployeeID)
        @Html.HiddenFor(m => m.EmployeeNotification[i].EmployeeName)
        @Html.CheckBoxFor(m => m.EmployeeNotification[i].Notify, new { @class = "notify" })
        <input type="hidden" name="EmployeeNotification.Index" value="@i" /> // add this
    }
    

    此外,我建议您删除除ID proeprty(我假设是)之外的其他隐藏输入 NotificationID ). 它只是包含不必要的html,因为保存数据不需要这些属性,它只是允许恶意用户更改这些值。我还建议您的视图模型包含 bool IsEditable 属性,并在将数据模型映射到视图模型时根据GET方法中的条件设置该值,以便 if 方块变成了正义 @if (Model.EmployeeNotification[i].IsEditable) { ... } else { ... }

        2
  •  0
  •   Sascha    6 年前

    我还设法从斯蒂芬的建议中得到一些灵感,找到了另一个解决上述问题的方法。不是很干净,但是嘿,它很管用。我绝对推荐斯蒂芬的代码。更加简洁明了。

    1. @Html.CheckBox("cb_Notify", Model.EmployeeNotification[i].Notify, new { type = "hidden" })
      @*Do not allow editing of the Notify field for employees who have been sent the notification already*@
      @if (Model.EmployeeNotification[i].NotifiedOn >= DateTime.Parse("2000-01-01 12:00:00 AM"))
      {
          @Html.DisplayFor(modelItem => Model.EmployeeNotification[i].Notify)
      }
      else
      {
          @*Hidden items for the post back information*@
          @Html.HiddenFor(modelItem => Model.EmployeeNotification[i].NotificationID)
          @Html.HiddenFor(modelItem => Model.EmployeeNotification[i].EmployeeID)
          @Html.CheckBoxFor(modelItem => Model.EmployeeNotification[i].Notify, new { @class = "notify" })
      }
      
    2. 然后对于jquery,使用hidden复选框遍历所有行并设置需要设置的值:

      // cache for performance
      var checkAll = $('#checkAll');
      
      checkAll.click(function () {
          var maxCount = $("input[id='cb_Notify']").length;
          var loopCounter;
          var customer;
          for (loopCounter = 0; loopCounter < maxCount; loopCounter++) {
              customer = $("input[name='EmployeeNotification[" + loopCounter + "].EmployeeName']").val();
              if (customer != null) {
                  $("input[name='EmployeeNotification[" + loopCounter + "].Notify']").prop("checked", this.checked);
              }
          }
          toggleSetAllCheckBoxStates();
      })
      

    toggleSetAllCheckBoxStates()函数是我创建的,因为它的第二个要求(不在这个问题的范围内,所以我不考虑它)是基于其数据设置只选择雇员数据的子集。但它遵循与上述示例相同的路线。

    通过这种方式,在post back事件中,我过滤掉了空数据,因为已发送通知的数据不包含EmployeeID。其余数据保存成功。