2

モーダルポップアップを使用してデータを更新する方法を探していました。 すでに他の devexpress コントロールを使用しているため、現在は devexpress を使用しています (ただし、jquery ライブラリがより簡単になると、これは変わる可能性があります!!)

私は検証の側面にこだわっています。率直に言って、私が達成しようとしていることに対して、プロセス全体は非常に難しいようです。

とにかく、私が現在取り組んでいるプロセスを説明しましょう。

-インデックスページには、更新可能なさまざまな要素の概要が含まれています。HtmlExtension を使用して、ポップアップを開いたときに編集ページをロードする devexpress ポップアップを作成できました。=> @Html.PopupControl().WithText("Edit").PopupGoesTo(Url.Action("EditPopup" など)

- 部分的なビューである編集ページは問題なく動作します。10 進数を取る 1 つのテキスト ボックスを含む小さなテスト ページを作成しました。

ajaxを使用してフォームを送信したい(率直に言って、ポップアップを作成してデータをそれにバインドし、検証をトリガーできる必要があるため、完全なポストバックを行う場合に検証を表示する方法がわからないため)エラー)。

  <script type="text/javascript">
    function EndPopUpUpdate(message) {
        if (message.url) {
            window.locatin.href = url;
        }
        $("#submitButtonPopUp, #loadingPopUp").toggle();
    }

    function BeginPopUpUpdate() {
        $("#submitButtonPopUp, #loadingPopUp").toggle();
    }
</script>

using (Ajax.BeginForm("Edit", "xxx", new AjaxOptions {  UpdateTargetId = "PopUpDiv", HttpMethod = "Post", OnBegin = "BeginPopUpUpdate", OnComplete = "EndPopUpUpdate"}, new { id = "PopUpForm" }))
    {
        <div id="PopUpDiv">
            @Html.Partial("EditPopup", new xxxViewModel())
        </div>
    }

jqueryイベントを手動で再フックすることにより、ポストバック時に検証を達成できました(ページが動的にロードされるため、これらはフックされないため)

function ReconnectValidation() {
    $("#PopUpForm").ready(function () {
        $.validator.unobtrusive.parse("#PopUpForm");
    });

    $("#submitButton").click(function (e) {
        var form = $("#PopUpForm");
        if (!form.valid()) {
            e.preventDefault();
        }
    });
}

したがって、これはクライアント側の検証を処理します。

さて、私の実際の問題!サーバー側の検証。

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([ModelBinder(typeof(CommandModelBinder))] UpdateCommand command)
    {
        if (!ModelState.IsValid)
        {
            //using the command pattern
            var handlerResult = HandlerLocator.GetQueryHandler<IGetOverviewHandler>().Execute(..);
            return PartialView("EditPopUp", handlerResult.ViewModel);
        }

        HandlerLocator.GetCommandHandler<UpdateCommand>().Handle(command);
        var returnLink = Url.Action("Index", new {..});
        return Json(new { url = returnLink }, JsonRequestBehavior.AllowGet);
    }

私は CustomModelBinder を作成しました。これは、コマンド オブジェクト (必要に応じて私の戻りモデル) のプロパティを検索し、同じ名前の一致するオブジェクトが見つかるかどうかをフォーム コレクションで検索します。次に、それを変換しようとし、失敗した場合は ModelError を ModelState にバインドします。

これで、有効または無効の ModelState ができました。有効な場合は、インデックスにリダイレクトします (概要を更新できるようにします)。ajax.BeginForm は "PopUpDiv"-div を結果に置き換えるため (ページ内に同じページを作成するだけ)、クライアント側でこれを処理する必要があることを読みました。

onComplete イベントは次のとおりです。

function EndPopUpUpdate(message) {
            if (message.url) {
                window.locatin.href = url;
            }
            $("#submitButtonPopUp, #loadingPopUp").toggle();
        }

問題は、json メッセージを受信しないが、PartialView を受信することです。これは、私が受け取ったものではないので、message.url にアクセスできないことを意味します:/

それが問題番号1です

オブジェクトが有効でない場合は、モデルを含むパーシャルビューを返し、ユーザーにエラーを表示したいと考えています。部分ビューを返すと、現在のビューが置き換えられるだけですが、検証エラーは表示されません..

それが問題番号2です:)

また、この問題を解決するためのより良い方法を知っている場合は、遠慮なく返信してください (この方法は、それが何をするか、または何をすべきかについて本当に複雑に見えるため)

長い投稿で申し訳ありませんが、すべてが明確であることを願っています。

あなたの助けと時間をありがとう!

4

1 に答える 1

4

以前に jQuery UI () のダイアログ プラグインを使用したことがありますが、これはうまく機能することがわかりました。私は通常、ポップアップ内のiframeで開くリンクを取得します。これにより、ページが動的に読み込まれるためにjQuery検証イベントが接続されないという問題を回避できます-クライアント側とサーバー側の両方の検証が通常どおり機能するはずです、この iframe 内だけです。

この手法の良い点は、インデックス ページ内で通常どおりアクション リンクを生成できることです。たとえば、ポップアップのクラスをそれらに追加するだけです。

@Html.ActionLink("Edit", "Edit", new { id = Model.Id }, new { @class = "popup" })

次に、これらのリンクを取得して、次のような jQuery を使用してダイアログ iframe で開くことができます。

$("a.popup").click(function(e) {
    e.preventDefault();
    $("<iframe />").attr("src", $(this).attr("href") + "?popup=true").dialog({ show: "fadeIn", modal: true, width: 300, height: 300});
});

これは基本的にポップアップ リンクを探し、デフォルトの動作 (ページ ナビゲーション) をキャンセルし、ポップアップ内の iframe でその URL を開き、ページがポップアップ内にあることを識別するクエリ文字列を追加します。このクエリ文字列の理由と、それがポップアップであることを知っているため、おそらくアクション フィルターを使用して、ビュー内に別のレイアウト ページを読み込むことができます。

public class Popup : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Result != null
            && filterContext.Result is ViewResult
            && filterContext.RequestContext.HttpContext.Request["popup"] == "true")
            (filterContext.Result as ViewResult).MasterName = "~/Views/Shared/_PopupLayout.cshtml";
    }
}

これは、アクション メソッドを適用するクラスにこの属性を簡単に適用できることを意味します。この方法はまた、将来実装について考えが変わった場合 (つまり、ポップアップを削除する場合)、クリックをキャンセルする jQuery を簡単に削除できることを意味し、アプリは別個のページを持つ通常の MVC アプリとして引き続き機能します。ナビゲーション/検証などは「うまくいく」でしょう。

すべてが理にかなっていて、役立つことを願っています。

于 2012-08-06T16:46:47.320 に答える