Модальное окно bootstrap для редактирования форм

в 5:49, , рубрики: .net, ajax, ASP, Bootstrap, mvc, метки: , , ,

Возникла необходимость использовать плагин bootstrap-modal.js для редактирования формы. Казалось бы тривиальная задача, но пришлось столкнуться с некоторыми сложностями. В данной статье поделюсь с вами своим решением, более изящные решения и здоровая критика приветствуются.

Имеется страница с формой для редактирования товара. Добавим на форму выпадающий список с перечнем производителей. Рядом разместим бутстраповскую иконку icon-plus-sing, которая и будет триггером для вызова модального окна.

image

<div id="edit_producer" class="modal fade hide in">
</div>

<div class="editor-label">
    @Html.LabelFor(model => model.Producers)
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.ProducerId, Model.Producers)
    @Ajax.RawActionLink(
                        "<i class='icon-plus-sign icon-2x'></i>",
                        ActionConstants.Edit,
                        ProducerController.Name,
                        null,
                        new AjaxOptions
                            {
                                UpdateTargetId = "edit_producer",
                                InsertionMode = InsertionMode.Replace,
                                HttpMethod = "GET",
                                OnSuccess = "ShowProducerEditModal"
                            },
                        null)

    @Html.ValidationMessageFor(model => model.Producers)
</div>
</div>

Примечание: используются кастомные html-хелперы DropDownListFor и RawActionLink.

Идем дальше. Пишем js обработчик на событие OnSuccess.

function ShowProducerEditModal() {
     $('#edit_producer').modal('show');
 }

Далее нам нужен экшен в контроллере ProducerController для рендеринга содержимого модального окна.

[HttpGet]
public ActionResult Edit(long? id)
{
    ProducerEditModel model = service.GetProducerEditModel(id);
    return PartialView("ProducerEditPartial", model);
}

Частичное предстваление контента модального окна:

@using (Ajax.BeginForm(
                ActionConstants.Edit,
                ProducerController.Name,
                new AjaxOptions
                    {
                        HttpMethod = "POST",
                        OnSuccess = "OnSuccess"
                    }))
{
    <div class="modal-header">
        <a class="close" data-dismiss="modal">×</a>
        <h3>Редактирование производителя</h3>
    </div>
    <div class="modal-body">
        @Html.HiddenFor(model => model.Id)

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>
    </div>
    <div class="modal-footer">
        <input type="submit" class="btn btn-success" value="Сохранить" />
        <a href="#" class="btn" data-dismiss="modal">Close</a>
    </div>
}

В результате получаем красивый попап с формой по клику на триггер.
image

Следом стоит задача валидации редактируемой формы и добавление нового элемента в выпадающий список. Для этого пишем обработчик события OnSuccess. Предусмотрим возможность добавления и редактирования элемента выпадающего списка. Если содержимое формы оказывается не валидным, то отрисовываем форму внутри модального окна ещё раз.

function OnSuccess(data) {
    if (data.isValid) {
        $('#edit_producer').modal('hide');
        if (data.isNew) {
            AppendToDropDownList(data.name, data.id, 'ProducerId');
        } else {
            EditDropDownListItem(data.name, data.id, 'ProducerId');
        }
    } else {
        $('#edit_producer').html(data.partialView);
    }
}

function AppendToDropDownList(text, value, ddlId) {
    var newItem = $('<option/>', {
        value: value,
        text: text
    });

    $('#' + ddlId).append(newItem);
}

function EditDropDownListItem(text, value, ddlId) {
    $('#' + ddlId + ' option[value="' + value + '"]').text(text).val(value);
}

В контроллер ProducerController пишем ещё один экшен.
Примечание: используется кастомный статический метод RenderRazorViewToString

[HttpPost]
public ActionResult Edit(ProducerEditModel model)
{
    if (ModelState.IsValid)
    {
        bool isNew = model.Id == 0;
        long id = service.Save(model);
        return Json(new
            {
                isValid = true,
                id = id,
                name = model.Name,
                isNew = isNew
            });
    }

    return Json(new
    {
        partialView = RenderUtils.RenderRazorViewToString(this, "ProducerEditPartial", model),
        isValid = false
    });
}

image

В общем-то на этом все. Спасибо за внимание.

Полезные ссылки:
Русскоязычное руководство по bootstrap
Туториал по bootstrap-modal.js
Исходники bootstrap-modal.js

Автор: ne4ta

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js