Установите флажок Все в редакторе для MVC C # View - PullRequest
0 голосов
/ 07 сентября 2018

Мой текущий вид отображает список сотрудников. Все отображаемые строки и столбцы привязаны к модели.

См. Мой код для просмотра ниже:

@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) и сохранить данные в событии обратной отправки. Как установить флажок «Выбрать все» для работы с флажком «Редактор для» или «флажок для модели».

Для меня именованная опция CheckBox работает, как и предполагалось, с полем «Выбрать все», но мне не удается вернуть данные в обработчик событий после события. Данные модели для выбранного столбца Уведомление возвращаются как ноль.

Основная проблема, которую я предполагаю, заключается в том, как автоматизация называет элементы для флажков, если я смотрю на сгенерированные коды элементов name и 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, в обработчике событий post.

Я не смог получить ответы, которые мне нужны, на другие похожие вопросы на флажках «Выбрать» или «Отметить все», так как они, похоже, используют другие языки кодирования. Пожалуйста помоги.

Обратите внимание:

Просто чтобы подчеркнуть очевидное: намерение состоит в том, чтобы сохранить только один из выбираемых флажков Уведомлять в конце. Тот, который будет работать. Не все трое. Я просто покажу их из-за неудачного тестирования и отладки.

Ответы [ 2 ]

0 голосов
/ 08 сентября 2018

Мне также удалось найти другое решение для поста Стивена выше, используя вдохновение из его предложений. Не так чисто, но эй, это работает. Я определенно рекомендую код Стивена. Гораздо чище и лаконичнее.

  1. Переместите и скройте пользовательский флажок 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" })
    }
    
  2. Затем для 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 на основе своих настроек данных. Но это следует в том же духе, что и в приведенном выше примере.

Таким образом, в событии post back я отфильтровал нулевые данные, поскольку те, для которых были отправлены уведомления, не будут содержать EmployeeID. Остальные данные успешно сохранены.

0 голосов
/ 08 сентября 2018

Поскольку ваши атрибуты nameid) включают индексатор коллекции, вы можете использовать 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")), тогда ваше свойство EmployeeNotification будет иметь значение null в методе POST. В качестве альтернативы, если, скажем, 3-й элемент соответствует этому условию, то EmployeeNotification будет содержать только первые 2 записи. Вам нужно добавить дополнительный вход для индексатора коллекции, чтобы позволить 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
}

Кроме того, я рекомендую вам удалить другие скрытые входы, кроме того, который является идентификатором proeprty (который я предполагаю NotificationID). Это просто включает ненужный HTML, так как эти свойства не требуются для сохранения данных, и он просто позволяет злоумышленникам изменять эти значения. Я также рекомендую, чтобы ваша модель представления содержала (скажем) свойство bool IsEditable, и вы устанавливаете это значение на основе условия в методе GET при сопоставлении модели данных с моделью представления, чтобы блок if становился просто * 1024. *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...