web-dev-qa-db-ja.com

検証付きのjQueryを使用してModal内で.NET MVCフォームを作成する方法

私はこれをすべてまとめる方法を知ることに本当に苦労しています。検証の有無にかかわらず、.net MVCページ内にフォームを何度も作成しました。そして、jQueryを使用して、検証ありと検証なしのフォームを作成しました。また、モーダル内にフォームを作成しましたが、MVCを使用したことはありません。

元の質問 から理解できるのは、このフォームはモーダル内にあるため、jQueryを使用して送信を処理する必要があるからです。私は、これらすべての動くピースをどのようにまとめるかを考え出すのにかなりの時間を費やしています。これまでのところ、これをすべてまとめたチュートリアル(またはチュートリアルのコンボ)は見つかりませんでした。

必要なものは次のとおりです。

  • MVCビューの内部には、モーダルを開くボタンがあります。 (これは正常に動作します。)
  • モーダルが開くと、複数のテキストフィールドとドロップダウンを持つフォームが含まれます。それぞれが必要です。 (必須フィールドを作成するには、MVCフォームで通常行うように、ビューのモデルでこれらを定義しますか?またはjQueryで要件を作成しますか?)
  • ユーザーがフォームを送信しようとして空または無効な場合、モーダルは開いたままで、検証メッセージが表示されます。 (私の 元の質問 から、これはモーダルのためにストレートMVCを使用することは不可能であり、jQueryが必要であることを理解しています。ここでは失われました。)
  • ユーザーがフォームを送信しようとし、すべてのフィールドが有効な場合、モーダルが閉じ、コントローラーを押してフィールドをデータベースに保存します。 (jQueryから抜け出す方法がわからず、通常のコントローラーを押して最終的なロジックを処理するだけです。)

編集:

ジェイソン、助けてくれてありがとう!あなたの提案に基づいて、これは私がそれを機能させた方法です。

親ビュー:

モーダル:

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

    }
20
Casey Crookston

組み込みの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);
}
_

ただし、ここでの問題は、「成功」または「検証失敗」のどちらが発生しているかわからないことです。検証エラーはHTTP 200応答と見なされるため、error: function(err){ }ハンドラーを追加しても役に立ちません。どちらの場合も、divコンテンツは置き換えられ、ユーザーは手動でモーダルを閉じる必要があります。 are両方の条件を区別するために追加のデータを渡す方法がありますが、それは別の長い回答の投稿です。

34
Jasen

PartialViewをレンダリングする代わりに、モーダルdiv内にiframeを配置することを検討してください。この方法で、送信、モデル化、必要なものなどの単純なページを開発するのと同じ方法でモーダルセクションを開発できます。

こちらです:

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