如何使用带有验证的 jQuery 在 Modal 中创建 .NET MVC 表单

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31053460/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 16:46:41  来源:igfitidea点击:

How to make a .NET MVC Form inside a Modal using jQuery with validation

jqueryasp.net-mvcformsmodal-dialog

提问by Casey Crookston

I am really struggling with knowing how to put this all together. I've built forms inside .net MVC pages plenty of times, with and without validation. And I've built forms using jQuery, with and without validation. And I've built forms inside of a modal, but never with MVC.

我真的很难知道如何把这一切放在一起。我已经多次在 .net MVC 页面中构建表单,无论是否经过验证。我已经使用 jQuery 构建了表单,无论是否经过验证。我已经在模态中构建了表单,但从未使用 MVC。

I understand from my original questionthat because this form is inside a modal that I'll need to use jQuery to handle the submit. I am having a heck of a time figuring out how to put all these moving pieces together. So far, I've not found a tutorial (or combo of tutorials) that puts this all together.

我从我原来的问题中了解到,因为这个表单在一个模态内,所以我需要使用 jQuery 来处理提交。我花了很长时间想办法把所有这些移动的部分放在一起。到目前为止,我还没有找到将所有这些放在一起的教程(或教程组合)。

Here is what I need:

这是我需要的:

  • Inside of my MVC view there is a button that opens a modal. (This works fine.)
  • Once the modal opens, it contains a form with several text fields and dropdowns. Each is required. (To make the fields required, would I define these in the view's model, as I normally would with an MVC form? Or do I create the requirements in the jQuery?)
  • If the user attempts to submit the form and they are empty or invalid, the modal stays open and the validation messages appear. (I understand, from my original question, that this is not possible using straight MVC because of the modal, and that some jQuery is needed. I'm lost here.)
  • If the user attempts to submit the form and all fields are valid, then the modal closes, we hit the controller and save the fields to the db. (Not sure how to escape out of the jQuery and just hit the normal controller to handle the final logic.)
  • 在我的 MVC 视图中有一个按钮可以打开一个模式。 (这很好用。)
  • 模式打开后,它包含一个带有多个文本字段和下拉列表的表单。每个都是必需的。 (为了使字段成为必需的,我会在视图的模型中定义这些字段吗,就像我通常使用 MVC 表单所做的那样?或者我是否在 jQuery 中创建需求?)
  • 如果用户尝试提交表单并且表单为空或无效,则模式将保持打开状态并显示验证消息。 (我从我最初的问题中了解到,由于模式的原因,使用直接 MVC 是不可能的,并且需要一些 jQuery。我在这里迷路了。)
  • 如果用户尝试提交表单并且所有字段都有效,则模式关闭,我们点击控制器并将字段保存到数据库。 (不知道如何从 jQuery 中逃脱,然后点击普通控制器来处理最终逻辑。)

EDIT:

编辑:

Thank you, Jason, for your help! Based on your suggestions, this is how I got it working.

谢谢你,杰森,谢谢你的帮助!根据您的建议,这就是我的工作方式。

The Parent View:

父视图:

The modal:

模态:

<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>

And then here's the scripts:

然后这里是脚本:

@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>
}

The Partial View (slimmed down):

局部视图(瘦身):

@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>
}

The Controller:

控制器:

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

        return PartialView("_AccountProfileEdit", model);

    }

回答by Jasen

You can use the built-in MVC validation scripts along with the data annotaions on your model

您可以使用内置的 MVC 验证脚本以及模型上的数据注释

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

Make a partial view to hold your modal form.

制作一个局部视图来保存您的模态表单。

_AccountProfileEdit.cshtml

_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>
}

Then reference this in your modal box. If you want pre-populated model you'll need to render an action:

然后在您的模态框中引用它。如果你想要预先填充的模型,你需要渲染一个动作:

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

If you just want a blank form then you can just use:

如果您只想要一个空白表格,那么您可以使用:

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

The action uses the idparameter to fetch and populate the model

该操作使用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 POST

Now you'll need AJAX to submit this form. If you rely on a standard form submission the browser will navigate away from your page (and close your modal).

现在您需要 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);
        }
    });
});

You need to use the event delegate $(staticParent).on(event, target, handler)for the submit event because the form content may be replaced later.

您需要$(staticParent).on(event, target, handler)为提交事件使用事件委托,因为稍后可能会替换表单内容。

Post Action

发布操作

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

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

    return PartialView("_AccountProfileEdit", model);
}

Client-side validation scripts should prevent them from ever submitting. But if that somehow failed or if you can't validate something on the client then you have ModelState.IsValid. You might also invalidate something server-side manually.

客户端验证脚本应该阻止它们提交。但是,如果这以某种方式失败了,或者您无法在客户端上验证某些内容,那么您将拥有ModelState.IsValid. 您也可以手动使服务器端的某些内容无效。

_AccountEditSuccess.cshtml

_AccountEditSuccess.cshtml

And the "success" partial view.

以及“成功”的部分观点。

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

Not Valid is a Fail, Right?

无效就是失败,对吧?

From your AJAX success handler you have

从你的 AJAX 成功处理程序你有

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

But the problem here is we don't know if you are getting a "success" or "validation failure". Adding an error: function(err){ }handler won't help because the validation failure is considered a HTTP 200response. In both cases the div content is replaced the user will need to manually close the modal. There areways to pass additional data to distinguish both conditions but that's another long answer post.

但这里的问题是我们不知道您是“成功”还是“验证失败”。添加error: function(err){ }处理程序无济于事,因为验证失败被视为HTTP 200响应。在这两种情况下,div 内容都被替换,用户需要手动关闭模态。有一些方法可以传递额外的数据来区分这两种情况,但这是另一个很长的回答帖子。

回答by Elisheva Wasserman

Consider put an iframe inside the modal div, instead of rendering partialView, this way you can develop the modal section the same way you develop simple pages, which submit, model, required etc...

考虑在模态div中放置一个iframe,而不是渲染partialView,这样你就可以像开发简单页面一样开发模态部分,提交,模型,需要等......

this way:

这边走:

<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>