Как создать форму .NET MVC внутри модала с помощью jQuery с проверкой

Я действительно изо всех сил стараюсь понять, как все это сделать. Я много раз создавал формы внутри .net MVC-страниц, с проверкой и без нее. И я создал формы, используя jQuery, с и без проверки. И я создал формы внутри модального, но никогда не с MVC.

Я понимаю из своего оригинального вопроса, потому что эта форма внутри модала, что мне нужно будет использовать jQuery для обработки submit. У меня есть чертовски время выяснить, как собрать все эти движущиеся части вместе. До сих пор я не нашел учебника (или комбо учебников), который объединяет все это.

Вот что мне нужно:

  • Внутри моего MVC-представления есть кнопка, которая открывает модальную. (Это прекрасно работает.)
  • Как только модальный файл открывается, он содержит форму с несколькими текстовыми полями и выпадающими меню. Каждый из них требуется. (Чтобы сделать нужные поля, я бы определил их в модели представления, как обычно, с формой MVC? Или я создаю требования в jQuery?)
  • Если пользователь пытается отправить форму, и они пусты или недействительны, модальная версия остается открытой и появляются сообщения проверки. (Я понимаю, из моего оригинального вопроса, что это невозможно, используя прямой MVC из-за модальности, и что требуется какой-то jQuery. Я потерялся здесь.)
  • Если пользователь пытается отправить форму, и все поля являются допустимыми, тогда модальная закрывается, мы нажимаем на контроллер и сохраняем поля в db. (Не уверен, как выйти из jQuery и просто нажать на обычный контроллер для обработки конечной логики.)

EDIT:

Спасибо, Джейсон, за вашу помощь! Основываясь на ваших предложениях, вот как я работал.

Родительский просмотр:

Модальный:

<div class="modal fade" id="AccountEditModal" tabindex="-1" role="dialog" aria-labelledby="AccountEditModalLabel">
    <div class="modal-dialog modalAccountEdit" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h3><strong>Edit Account Profile - <span class="accountname"></span></strong></h3>
            </div>

            <div class="modal-body">
                <div id="formContent">
                    @Html.Partial("_AccountProfileEdit", new GEDCPatientPortal.Models.AccountProfileEditViewModel())
                </div>
            </div>
        </div>
    </div>
</div>

И тут скрипты:

@section Scripts {
    <script>
        $(document).ready(function () {

            $('#AccountEditModal').on('shown.bs.modal', function () {
                $('#myInput').focus()
            })



        $("#AccountEditModal").on("submit", "#form-accountprofileedit", function (e) {
            e.preventDefault();  // prevent standard form submission

            var form = $(this);
            $.ajax({
                url: form.attr("action"),
                method: form.attr("method"),  // post
                data: form.serialize(),
                success: function (partialResult) {
                    $("#formContent").html(partialResult);
                }
            });
        });


        });

    </script>
}

Частичный вид (уменьшенный):

@using (Html.BeginForm("AccountProfileEdit", "Account", FormMethod.Post, new { id = "form-accountprofileedit", @class = "full-form" }))
    {


    @Html.CustomTextboxFor(model => model.Address)


    <div style="text-align:right;">
        <button type="submit" id="accountprofileedit-submit" name="accountprofileedit-submit" value="Edit Account" class="btn btn-primary" style="margin-left:5px;">Edit Account</button>
        <button type="button" class="btn btn-primary" data-dismiss="modal">Cancel</button>
    </div>
}

Контроллер:

    [HttpPost]
    public ActionResult AccountProfileEdit(AccountProfileEditViewModel model)
    {
        if (ModelState.IsValid)
        {
            // logic to store form data in DB
        }

        return PartialView("_AccountProfileEdit", model);

    }

Ответ 1

Вы можете использовать встроенные сценарии проверки MVC вместе с аннотациями данных на вашей модели

public class AccountProfileEditViewModel
{
    [Display(Name = "Address")]
    [Required()]
    [StringLength(200)]
    public string Address { get; set; }
}

Сделайте частичный вид для хранения вашей модальной формы.

_AccountProfileEdit.cshtml

@model AccountProfileEditViewModel

@using(Html.BeginForm("AccountProfileEdit", "Account",
           FormMethod.Post, new { id = "form-accountedit-appt" }) {
    @Html.ValidationSummary(true)

    @Html.LabelFor(m => m.Address)
    @Html.TextBoxFor(m => m.Address)
    @Html.ValidationMessageFor(m => m.Address)
    <button type="submit">Edit</button>
}

Затем укажите это в своем модальном поле. Если вам нужна предварительно заполненная модель, вам необходимо выполнить действие:

<div class="modal-body" id="form-container">
    @Html.Action("AccountProfileEdit", "Account", new { id=account.Id })
</div>

Если вам просто нужна пустая форма, вы можете просто использовать:

<div class="modal-body" id="form-container">
    @Html.Partial("_AccountProfileEdit")
</div>

Действие использует параметр id для извлечения и заполнения модели

[HttpGet]
public ActionResult AccountProfileEdit(int id)
{
    AccountProfileEditViewModel model = db.GetAccount(id);  // however you do this in your app

    return PartialView("_AccountProfileEdit", model);
}

AJAX POST

Теперь вам понадобится AJAX для отправки этой формы. Если вы полагаетесь на стандартное представление формы, браузер будет перемещаться от вашей страницы (и закрыть ваш модальный).

$("#myModal").on("submit", "#form-accountedit", function(e) {
    e.preventDefault();  // prevent standard form submission

    var form = $(this);
    $.ajax({
        url: form.attr("action"),
        method: form.attr("method"),  // post
        data: form.serialize(),
        success: function(partialResult) {
            $("#form-container").html(partialResult);
        }
    });
});

Вам нужно использовать делегат события $(staticParent).on(event, target, handler) для события отправки, потому что содержимое формы может быть заменено позже.

Сообщение о действии

[HttpPost]
public ActionResult AccountProfileEdit(AccountProfileEditViewModel model)
{
    // Request.Form is model

    if (ModelState.IsValid)
    {
        // do work
        return PartialView("_AccountEditSuccess");
    }

    return PartialView("_AccountProfileEdit", model);
}

Сценарии проверки на стороне клиента должны препятствовать их отправке. Но если это как-то не удалось или если вы не можете проверить что-то на клиенте, то у вас есть ModelState.IsValid. Вы также можете сделать недействительным что-то серверное вручную.

_AccountEditSuccess.cshtml

И частичное представление "успех".

<div>Success! <button>Click to close</button></div>

Недействительно является ошибкой, правильно?

Из вашего обработчика успеха AJAX у вас есть

success: function(partialResult) {
    $("#form-container").html(partialResult);
}

Но проблема здесь в том, что мы не знаем, получаете ли вы "успех" или "отказ проверки". Добавление обработчика error: function(err){ } не поможет, поскольку отказ проверки считается ответом HTTP 200. В обоих случаях содержимое div заменяется, пользователю необходимо вручную закрыть модальный. Есть способы передать дополнительные данные, чтобы отличить оба условия, но это еще один длинный ответ.

Ответ 2

Рассмотрите возможность размещения iframe внутри модального div, вместо рендеринга partialView, таким образом вы можете развить модальный раздел так же, как вы разрабатываете простые страницы, которые представляют, модели, необходимые и т.д.

следующим образом:

<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog modalAE" role="document">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <h3><strong>Edit Account Profile - <span class="accountname"></span></strong></h3>
        </div>
            <div class="modal-body">
          <iframe src='myApp/AccountProfileEdit'/>
        </div>
        <div class="modal-footer">
            <button type="submit" id="accountprofileedit-submit" name="accountprofileedit-submit" value="Edit Account" class="btn btn-primary" style="margin-left:5px;">Edit Account</button>
            <button type="button" class="btn btn-primary" data-dismiss="modal">Cancel</button>
        </div>
        }
    </div>
</div>