6

オプションのクライアント側検証を使用して実装しようとしています

  • ASP.NET MVC 4、
  • 控えめなjQuery検証、
  • 控えめなJavaScript

これは正常に機能します

次の図は、オプションのクライアント側検証の意味を示しています。フォームの1つのフィールドにのみ電子メールが含まれていると予想されるため、電子メールバリデーターが添付されています。

ここに画像の説明を入力してください

次に、[保存]をクリックします。テキスト「name@doamin」は有効なメールアドレスではないため、検証の概要が表示されます。検証の概要とともに、 [とにかく保存]ボタンを非表示にします。

ここに画像の説明を入力してください

この2番目のボタンは、が付いている通常の送信ボタンですclass="cancel"jQuery.validate.jsこれは、このボタンを使用して送信するときに検証をスキップするようにスクリプトに指示します。

ビューのコードスニペットは次のとおりです。

@using (Html.BeginForm())
{
    <div>
        <input data-val="true" data-val-email="Uups!" name="emailfield" />
        <span class="field-validation-valid" data-valmsg-for="emailfield" data-valmsg-replace="false">*</span>
    </div>

    <input type="submit" value="Save" />
    @Html.ValidationSummary(false, "Still errors:")
    <div class="validation-summary-valid" data-valmsg-summary="true">
        <input type="submit" value="Save anyway" class="cancel" />
    </div>
}

これらはすべて正常に機能します。

問題

2番目の送信ボタン- 「とにかく保存」は、Ajaxフォームに切り替えると期待どおりに機能しなくなります。通常の動作と同じように動作し、検証が成功するまで送信を防ぎます。

「ajaxified」ビューのコードスニペットは次のとおりです。

@using (Ajax.BeginForm("Edit", new { id = "0" },
        new AjaxOptions
            {
                HttpMethod = "POST",
                InsertionMode = InsertionMode.Replace,
                UpdateTargetId = "ajaxSection",
            }))
{
    <div>
        <input data-val="true" data-val-email="Uups!" name="emailfield" />
        <span class="field-validation-valid" data-valmsg-for="emailfield" data-valmsg-replace="false">*</span>
    </div>

    <input type="submit" value="Save" />
    @Html.ValidationSummary(false, "Still errors:")
    <div class="validation-summary-valid" data-valmsg-summary="true">
        <input type="submit" value="Save anyway" class="cancel" name="saveAnyway" />
    </div>
}

違いを確認するためにデバッグjQuery.validation.jsしましたが、失敗しました。

質問

問題を修正または回避し、ajaxフォームを意図したとおりに動作させるためのアイデアは大歓迎です。


補遺

クライアント側の検証を行うことは絶対に必要です。サーバー側の検証はオプションではありません。トラフィックの増加(このサンプルは単純化されています。実際のフォームにははるかに多くのフィールドが含まれています)とレイテンシーの他に、サーバー側の検証では実行されないことが1つあります。クライアント側のバリデーターは、フォーカスが失われたときに誤ったフィールドを強調表示します。これは、次のフィールドにタブで移動するとすぐにフィードバックがあることを意味します。

4

3 に答える 3

11

これは、Microsoftの控えめなajaxスクリプトの既知の制限です。バグを修正するために変更することができます。したがって、jquery.unobtrusive-ajax.jsスクリプト内で144行目の次のように置き換えます。

$(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []);

と:

$(form).data(data_click, name ? [{ name: name, value: evt.target.value, className: evt.target.className }] : []);

さらに、クラス名をハンドラーに渡して、クライアント側の検証をトリガーするかどうかをハンドラーが決定できるようにします。現在、どのボタンがクリックされたかに関係なく、常に検証がトリガーされます。そして今、154行目で次のテストを変更します。

if (!validate(this)) {

と:

if (clickInfo[0].className != 'cancel' && !validate(this)) {

これにより、クラス名キャンセルの送信ボタンを使用してフォームを送信した場合に、クライアント側の検証がトリガーされなくなりました。もう1つの可能性は、jquery.unobtrusive-ajax.jsスクリプトをスクレイプして、プレーンな古いjQueryを使用して目立たないようにAJAXifyできるAjax.BeginForm標準に置き換えることです。Html.BeginForm

于 2012-07-26T06:07:59.453 に答える
7

最後に、それ自体が邪魔にならない解決策を見つけました

    // restore behavior of .cancel from jquery validate to allow submit button 
    // to automatically bypass all jquery validation
    $(document).on('click', 'input[type=image].cancel,input[type=submit].cancel', function (evt)
    {
        // find parent form, cancel validation and submit it
        // cancelSubmit just prevents jQuery validation from kicking in
        $(this).closest('form').validate().cancelSubmit = true;
        $(this).closest('form').submit();
        return false;
    });

注:最初に試したところ、これが機能していないように見える場合は、サーバーにラウンドトリップしてページをエラーで更新していないことを確認してください。他の方法でサーバー側の検証をバイパスする必要があります。これにより、フォーム.ignore内のすべてに属性を追加する手間をかけずに、フォームを送信できるようになります。

button(ボタンを使用している場合は、セレクターに追加する必要がある場合があります)

于 2013-07-01T09:56:26.827 に答える
-2

目立たない検証が必要ない場合は、それを無効にして、サーバー側ですべてのチェックを行います。

サーバー側の[送信]ボタンの値を確認し、それに基づいて続行できます。

name両方の送信入力に属性を追加します。

<input type="submit" value="Save" name="btnSubmit" />
<input type="submit" value="Save anyway" class="cancel" name="btnSubmit" />

アクションを更新して実行しますstring btnSubmit。モデルがある場合は、モデルに入れるだけです。

[HttpPost]
public ActionResult Edit(string emailfield, string btnSubmit)
{
    switch (btnSubmit)
    {
        case "Save":
            if(ModelState.IsValid)
            {
                // Save email
            }
            break;
        case "Save anyway":
            // Save email
            return RedirectToAction("Success");
            break;
    }
    // ModelState is not valid
    // whatever logic to re display the view
    return View(model);
}

アップデート

クライアントの検証によって作業が簡素化されることは理解していますが、Ajaxの何が問題になっているのかがわからない場合(class = "cancel"が入力で叩かれたときの動作に慣れていない場合)、検証するスクリプトを作成できます。サーバー側のフォーカスが解除された入力:

$('input[type=text]').blur(function(){
    $.ajax({
        url: '/ControllerName/ValidateInput',
        data: { inputName: $(this).val() },
        success: function(data) {
            //if there is a validation error, display it
        },
        error: function(){
            alert('Error');
        }
    });
});

次に、入力の検証を行うアクションを作成する必要があります。

public ActionResult ValidateInput(string inputName)
{
    bool isValid = true;
    string errorMessage = "";
    switch (inputName)
    {
        case "password"
            // do password validation
            if(!inputIsValid)
            {
                isValid = false;
                errorMessage = "password is invalid";
            }
            break;
        case "email"
            // do email validation
            if(!inputIsValid)
            {
                isValid = false;
                errorMessage = "email is invalid";
            }
            break;
    }
    return Json(new { inputIsValid = isValid, message = errorMessage });
}

少し面倒ですが、私が言ったように、クライアントの検証を理解していなければうまくいく可能性があります。


アップデート

なぜ私が最初にこれを考えなかったのかわからない...class="cancel"あなたに頼るのではなく、次のようなことをすることができます:

「とにかく」送信入力IDを指定します。

<input type="submit" value="Save anyway" class="cancel" name="btnSubmit" id="submitAyway" />

次に、次のようなスクリプトを作成します。

$('#submitAyway').click(function(evt) {
    evt.preventDefault();
    $('form').submit();
});

私はこれをテストしていませんが、理論的には、これは検証せずにフォームを送信する必要があります。最初の例で示したように、おそらくサーバー側の検証が必要になります。

于 2012-07-25T17:53:38.717 に答える