Пользователь
0,0
рейтинг
10 мая 2013 в 09:49

Разработка → Модальное окно bootstrap для редактирования форм из песочницы tutorial

Ajax*, ASP*, .NET*
Возникла необходимость использовать плагин 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
карма
6,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (4)

  • 0
    Для самой формы в попапах нужно нижний отступ ставить в 0, — иначе вот такая белая полоса под сохранить/закрыть.
    ps. Вроде бы всё логично и таки весьма тривиально, если с ajax-ом дружить :)
  • 0
    Только начал знакомиться с бутстрапом. Красоту наведу, спасибо за подсказку. А вот на счет решений, честно говоря, не нашел интересных примеров. Приятно, когда свой велосипед умеет ездить)
  • 0
    Ajax, модальные окна — круто что сайтики становятся по интерфейсу как десктопные проги.
  • 0
    Мне кажется пихать PartialView в JSON весьма корявое решение. Сам пришёл к мнению, что лучше отдавать результат IsValid в кастомных заголовках HTTP, и использовать нормальный рендер PartialView через return. Т.е. если в заголовке IsValid (имя параметра для заголовка можно подобрать), то обрабатывать пришедние данные как Json, а если нет, то отрендерить все что пришло как HTML.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.