如何使用带验证的jQuery在模式内生成.NETMVC表单

如何使用带验证的jQuery在模式内生成.NETMVC表单,jquery,asp.net-mvc,forms,modal-dialog,Jquery,Asp.net Mvc,Forms,Modal Dialog,我真的很难知道如何把这一切放在一起。我已经在.NETMVC页面中构建了很多表单,无论是否经过验证。我使用jQuery构建表单,有验证和无验证。我在modal中构建了表单,但从未使用MVC 我从我的经验中了解到,因为此表单在一个模式中,我需要使用jQuery来处理提交。我花了很长时间才弄明白如何把这些移动的部件放在一起。到目前为止,我还没有找到一个教程(或教程组合)把这一切放在一起 以下是我需要的: 在我的MVC视图中,有一个按钮可以打开一个模式。(这很好用。) 打开模式后,它将包含一个带有多个

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

我从我的经验中了解到,因为此表单在一个模式中,我需要使用jQuery来处理提交。我花了很长时间才弄明白如何把这些移动的部件放在一起。到目前为止,我还没有找到一个教程(或教程组合)把这一切放在一起

以下是我需要的:

  • 在我的MVC视图中,有一个按钮可以打开一个模式。(这很好用。)
  • 打开模式后,它将包含一个带有多个文本字段和下拉列表的表单。每个都是必需的。(为了使字段成为必需的,我会像通常使用MVC表单那样在视图的模型中定义这些字段吗?还是在jQuery中创建需求?)
  • 如果用户试图提交表单,但表单为空或无效,则模式将保持打开状态,并显示验证消息。(我从我的经验中了解到,由于模式的原因,使用纯MVC是不可能的,并且需要一些jQuery。我在这里迷路了。)
  • 如果用户试图提交表单,并且所有字段都有效,那么模式关闭,我们点击控制器并将字段保存到数据库。(不确定如何退出jQuery,只需点击普通控制器来处理最终逻辑。)
编辑:

@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);

    }
谢谢你,杰森,谢谢你的帮助!根据你的建议,我就是这样让它工作的

父视图:

@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);

    }
模式:

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

考虑在modal div中放置一个iframe,而不是呈现partialView,这样您可以像开发简单页面一样开发modal部分,这些页面包括submit、model、required等

这样:

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

&时代;
编辑账户档案-
编辑帐户
取消
}

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

public class AccountProfileEditViewModel
{
    [Display(Name = "Address")]
    [Required()]
    [StringLength(200)]
    public string Address { get; set; }
}
制作一个局部视图来保存模态形式

\u 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>
}
ajaxpost

现在您需要AJAX来提交此表单。如果您依赖标准表单提交,浏览器将离开您的页面(并关闭您的模式)

对于提交事件,您需要使用事件委托
$(staticParent).on(事件、目标、处理程序)
,因为表单内容以后可能会被替换

行动后

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

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

    return PartialView("_AccountProfileEdit", model);
}
客户端验证脚本应防止它们提交。但是,如果该操作以某种方式失败,或者无法在客户端上验证某些内容,那么您就拥有了
ModelState.IsValid
。您还可以手动使服务器端的某些内容无效

\u AccountEditSuccess.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>Success! <button>Click to close</button></div>

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

我在两个视图中使用jQuery.validate()构建MVC引导模式表单,一个是包含模式div和Html.BeginForm(…)的“main”视图,另一个是包含表单元素的模式体的部分视图,使用一个单独的.js文件,该文件包含用于打开模式、绑定局部视图及其表单验证的jQuery方法

它从主视图链接上的CSS类开始,该链接调用返回部分视图的ActionResult(),editChangeReason:

<a href="@Url.Action("_editCarrierChangeReason" ...)" class="editChangeReason">Add Exception</a>
在该主视图上,有一个典型的引导模式div,其中添加了@Html.BeginForm(…):


杰森,首先,谢谢你!我真的很感谢你的时间和帮助。第二,很抱歉,我花了这么长时间才回复。我一直在度假。但这仍然是我需要解决的一个问题。第三,我根据你的建议对我的作品进行了编辑。我确信我错过了一些简单的东西,但它仍然不起作用。提交时的导航通常意味着没有正确阻止默认提交。确保没有任何脚本错误。将提交处理程序移动到
$(document.ready()
中。作为一个健全的检查,删除ajax调用,您希望能够在不发生任何事情的情况下按下submit按钮。Bam!将脚本移动到$(document).ready()中才是关键!非常感谢你!假设表单提交后没有验证问题,如果我希望模态消失,该怎么办?我像您一样使用了代码,它的工作原理不同于将父页面加载到模式中,因为成功函数(partialResult)将html加载到我的模式的div标记中。如果存在任何验证问题,我会尝试将用户保持在模式中,但要更新数据库,关闭模式,然后转到父级,在父级中检查TempData以查看是否需要显示成功或失败消息。听起来您是在将完整页面视图而不是部分视图加载到模式中。你应该用你的代码创建一个新的问题——这将更容易看出你的例子中有什么不起作用。这是一个很好的解决方案。我确信这会激发我的一些本能,让我不以这种方式使用iFrame,但它融入MVC框架的自然方式使它引人注目。复活死人!5年前,我问了两个问题:)我对你的答案投了更高的票,仅仅是因为你付出了巨大的努力。
<div>Success! <button>Click to close</button></div>
success: function(partialResult) {
    $("#form-container").html(partialResult);
}
<a href="@Url.Action("_editCarrierChangeReason" ...)" class="editChangeReason">Add Exception</a>
public ActionResult _editCarrierChangeReason(string reasonId)
{
     ...
     return PartialView("modals/_modalEditCarrierChangeReason", rule);
}
<!-- START Carrier Change Reason/Exception Edit Modal -->
    <div id="editReason" class="modal fade in" data-backdrop="static" role="dialog">
        <div class="modal-dialog modal-lg" role="document">
            <div class="modal-content">
                @using (Html.BeginForm("_editCarrierChangeReason", "TmsAdmin", new { area = "Tms" }, FormMethod.Post, new { id = "formCarrierChangeReason", autocomplete = "off" }))
                {
                    <div id="editReasonContent">
                    </div>
                }
            </div>
        </div>
    </div>
<!-- END Carrier Change Reason/Exception Edit Modal -->
@Html.HiddenFor(m => m.TypeId)

<!-- START Modal Body -->
<div class="modal-body">

    <!-- START Carrier Exception Edit Form -->
    <div class="form-row">
        <div class="form-group col-6">
            <label class="control-label">Code</label> <span class="required">*</span>
            @Html.TextBoxFor(m => Model.Code, ...)
        </div>
    </div>
    <div class="form-row">
        <div class="form-group col">
            <label class="control-label">Description</label> <span class="required">*</span>
            @Html.TextAreaFor(m => Model.Description, ...)
        </div>
    </div>
    <!-- END Carrier Exception Edit Form -->
    ...
</div>
<!-- END Modal Body -->
$(document).ready(function() {
// Carrier Change Reason/Exception
        $("body").on("click", ".editChangeReason", function (e) {
            e.preventDefault();
            $("#editReasonContent").load(this.href,
                function() {
                    $("#editReason").modal({
                            keyboard: true
                        },
                        "show");
                    bindForm(this, "editChangeReason");
                    return;
                });
            return false;
        });   
});


// Allows modals to use partial views when using <a data-modal=""...></a> on parent View:
        function bindForm(dialog, type) {
            $("form", dialog).submit(function () {
                $.ajax({
                    url: this.action,
                    type: this.method,
                    data: $(this).serialize(),
                    success: function(result) {
                        switch (type) {
                        case "editChangeReason":
                            if (result.success) {
                                $("#editReason").modal("hide");
                                location.reload();
                            } else {
                                $("#editReasonContent").html(result);
                                bindForm();
                            }
                            return;
                        default:
                            break;
                        }
                    }
                });
                return false;
            });
        }
$("#formCarrierChangeReason").ready(function() {
    $("#formCarrierChangeReason").validate({
        rules: {
            Code: {required: true},
            Description: {required: true, minlength: 10}
        },
        messages: {
            Code: "Please enter a unique code no longer than 10 characters",
            Description: "Please add a description that explains this reason/exception"
        }
    });
});