我当前的视图显示的是员工列表。显示的所有行和列均受模型限制。
请参见下面的查看代码:
@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>
}
我的问题如下: 我可以使用第一条“通知复选框”代码行(即使用EditorFor和CheckBoxFor选项)手动选择所有“通知”复选框,并将数据保存在回发事件中。 如何获取全选复选框选项以在EditorFor或CheckBoxFor模型绑定复选框上使用。
对我来说,命名的CheckBox选项可以与“全选”框一起使用,但是我无法将数据返回到事件处理程序中。所选“通知”列的模型数据返回为空。
我假定的主要问题是,如果我在调试时查看生成的名称和id元素代码(示例输出源代码数据并添加了一些注释),则自动化为复选框的元素命名的方式:
<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中设置的值。
我无法在“选择”或“全部选中”复选框的其他类似问题中获得所需的答案,因为它们似乎使用其他编码语言。请帮忙。
请注意:
只需将显而易见的内容放在那里:目的是最后只保留可选的Notify复选框中的1个。一个会工作的。不是全部三个。由于测试和调试失败,我暂时只显示它们。
答案 0 :(得分:2)
由于您的name
(和id
)属性包括集合索引器,因此您可以使用jQuery 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"))
条件,则POST方法中的EmployeeNotification
属性将为null
。或者,如果说第三个项目满足该条件,那么EmployeeNotification
将仅包含前两个记录。您需要为集合索引器添加一个附加输入,以允许DefaultModelBinder
绑定非零/非连续索引器
@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身份(我假设是NotificationID
)之外。它只是包含不必要的html,因为保存数据不需要这些属性,它只是允许恶意用户更改这些值。我还建议您的视图模型包含一个(例如)bool IsEditable
属性,并且在将数据模型映射到视图模型时,应根据GET方法中的条件设置该值,以便使用if
块变成@if (Model.EmployeeNotification[i].IsEditable) { ... } else { ... }
答案 1 :(得分:0)
我也从斯蒂芬的建议中找到了灵感,从而找到了上述斯蒂芬帖子的另一种解决方案。不是很干净,但是,它可以工作。我绝对推荐斯蒂芬的代码。简洁明了。
将自定义cb_Notify复选框移动并隐藏到单元格的顶部,以便每行创建它。这将使其在所有行中都可搜索,等等,我可以在循环中使用它:
@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" })
}
然后对于jquery,使用隐藏的复选框循环遍历所有行并设置需要设置的值:
// 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()函数是由于存在第二个要求(超出此问题的范围,因此我将其保留),以便仅根据其数据设置选择Employee数据的子集。但这与上述示例相同。
这样,在回发事件中,我过滤掉了空数据,因为已发送通知的空数据将不包含EmployeeID。其余数据已成功保存。