jquery.validate.unobtrusiveが動的に挿入された要素で機能しない


99

私はで作業しASP.Net MVC3ていますjquery.validate.unobtrusive。クライアント検証を使用する簡単な方法は、を有効にすることです。サーバーからの問題では、すべてが正常に機能します。

しかし、JavaScriptを使用していくつかの新しい「入力」を注入しようとすると$.validator.unobtrusive.parse()、検証を再バインドするために呼び出す必要があることがわかりました。しかし、それでも、これらの動的注入フィールドはすべて機能していません。

さらに悪いことに、私jquery.validateは使用して手動でバインドしようとしましたが、それも機能しません。何かご意見は?


1
あなたがグーグルからここに来たなら、あなたはおそらく大いに賛成されている他のものは古いので@Sundara Prabuの答えを探しているでしょう。
マフィンマン

回答:


65

私の状況でこの問題を解決するjquery.validate.unobtrusiveライブラリの拡張機能を作成しました-興味深いかもしれません。

http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/


私はあなたの答えを正しいものに投票すべきだと思います。ところで、あなたのライブラリは最新のMVC RCで動作しますか?または彼らはそれを修正しましたか?
xandy

1
上記のリンクされたコードを使用する場合は、コメントにコードが含まれるようにコードを更新してください。そうしないと、コードが壊れる可能性があります。具体的には、2つのセレクター行を変更して、IDを二重引用符で囲みます。
Ryan O'Neill

1
いくつかのデバッグの後、これが私のシナリオで最終的に機能するようになりました。への呼び出しのため、入力セレクターではなく、入力の親またはフォームを渡す必要があります$.validator.unobtrusive.parse()。また、新しいルールを追加するだけで、既存のルールの更新を取得しないようです。
ランビネーター、2011年

5
この回答には、少なくともブログ投稿の弱点が含まれている必要があります。リンクのみの回答は一般的にSOのトピックから外れています
リアム

8
この回答は3+歳ですが、あなたがこのサイトで、ここでの回答の要部を投稿することができ、またはあなたの投稿は削除される危険かどうかは非常に参考になる、それはリンクよりかろうじてより」ある答えを言及よくある質問を参照してください。 '。必要に応じてリンクを含めることもできますが、これは「参照」としてのみです。答えはリンクを必要とせず、それ自体で成り立つべきです。
タリン

159

Xhalentのアプローチを試しましたが、残念ながらうまくいきませんでした。ロビンのアプローチは機能しましたが機能しませんでした。動的に追加された要素には効果的ですが、JQueryを使用してすべての検証属性とスパンをDOMから削除しようとした場合でも、検証ライブラリはそれらを検証しようとします。

ただし、「validationData」に加えてフォームの「unobtrusiveValidation」データを削除すると、検証するまたは検証しない要素を動的に追加および削除するのと同じように機能しました。

$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");

2
Xhalentも最初は機能しませんでしたが、解析には要素自体ではなく、新しい要素のコンテナを渡す必要があることに気付きました-簡単な修正は、要素ではなくフォーム全体を渡すことです-その後、魅力のように働いた。
パーHornshøj-Schierbeck

1
なぜそれvalidatorが定義されていないと言うのですか?validationとvalidation.unobtrusiveの両方を参照しています。検証は、これらのコードを呼び出すまで機能します
Shawn Mclean

4
ありがとう。これは、AJAX呼び出しを介して追加されたASP.MVC部分ビューのページに追加されたコンテンツに対して機能します。
Maksym Kozlenko 2012

これは助けてくれてありがとう。しかし、ページでアコーディオンを使用している問題に直面しています。アコーディオンが折りたたまれていると、検証が起動しません。どうすれば修正できますか?私は控えめなMVC3プラグインの代わりに、通常のjqueryの検証のために行っていた場合、私は私が言っていた、知っている$('#form').validate({ignore: ""})
parsh

1
それはPHPで私のために働いた。すべてのコメントが.NET MVCを指しているため、この情報を追加するだけです。:P
finnTheHumin 2014年

42

@viggityと@Robinsソリューションのシンプルさが本当に好きなので、簡単な小さなプラグインに変えました:

(function ($) {

    $.fn.updateValidation = function () {
        var $this = $(this);
        var form = $this.closest("form")
            .removeData("validator")
            .removeData("unobtrusiveValidation");

        $.validator.unobtrusive.parse(form);

        return $this;
    };
})(jQuery);

使用例:

$("#DischargeOutcomeNumberOfVisits")
    .attr("data-val-range-min", this.checked ? "1" : "2")
    .updateValidation();

$ .validator.unobtrusive.parse( "#" + form.attr( "id"));を置き換えます。$ .validator.unobtrusive.parse(form);
Softlion、2011

また、nearestは1つの要素しか返さないため、安全に.first()を削除することもできます。
Softlion、2011

ニース、私はこの単純なアプローチが好きです
nixon '16 / 11/12

data-val属性の追加と削除の両方で美しく機能します
Julian Dormon 2013

33

私も同じ問題を抱えています。同じフォームで$ .validator.unobtrusive.parse()を2回呼び出すことができないことを発見しました。最初にサーバーからフォームをロードするとき、フォームは邪魔にならないライブラリによって自動的に解析されます。入力要素をフォームに動的に追加し、$。validator.unobtrusive.parse()を再度呼び出すと、機能しません。同じことがparseElement()にも言えます。

控えめなlibは、jquery validateプラグインのvalidateメソッドを呼び出して、すべてのルールとメッセージを設定します。問題は、再度呼び出されたときに、プラグインが指定された新しいルールのセットを更新しないことです。

私は1つの大まかな解決策を見つけました:邪魔にならないlibでparseメソッドを呼び出す前に、フォームバリデーターを捨てます:

$('yourForm').removeData("validator");

さて、validateメソッドが控えめなlibによって呼び出されると、動的に追加された入力を含むすべてのルールとメッセージが再作成されます。

お役に立てれば


+1に
値する

2
Brad Wilsonsブログから:「jQuery.validator.unobtrusive.parseElement()関数を呼び出して、単一のHTML要素を解析することもできます。」何か助け?
jamesfm

@PerHornshøj-Schierbeck:@Robin van der Knaap:これを理解するのに最後の2〜3時間を費やしました!! とにかく、これは素晴らしく機能しました。原油は私がそれを使用するべきではないと感じさせます-なぜ私はこれをしたくないのですか?
KTF、

2
動的に追加されたバリデーターを含め、すべてのバリデーターが削除され、再び復元されるため、このソリューションは少し粗雑です。動的に追加されたバリデーターのみが更新された方がよいでしょう。@Xhalentは彼の回答でより明確なソリューションを提供しますが、基本的には、MSからの控えめなライブラリをこのシナリオ用に更新する必要があります。
Robin van der Knaap、

9

私はMVC 4とJQuery 1.8を使用しています。次のコードは、JqueryがAjax経由で動的に挿入されたコンテンツ、またはDOMへのJqueryを検証できるようにするために必要なようです。

新しく追加された要素のJqueryオブジェクトを受け入れるモジュラー関数を作成しました。tblContactsボタンのクリック時にJqueryを使用してID を持つ新しいテーブルを複製した場合は、jsファイルに以下の関数を含めます

function fnValidateDynamicContent(element) {
    var currForm = element.closest("form");
    currForm.removeData("validator");
    currForm.removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse(currForm);
    currForm.validate(); // This line is important and added for client side validation to trigger, without this it didn't fire client side errors.
}

次のように呼び出します。

fnValidateDynamicContent("#tblContacts")

currform.validate(); 実際にはcurrForm.validate();である必要があります。(打ち間違え)。にもかかわらず共有するためのおかげで、これは私のために働いた
ジョンMcの

1
@JohnMcがタイプミスを修正しました
Sundara Prabu

これは私のために働いた唯一のものです(mvc 4とjquery 1.10)
マフィンマン

4

jquery検証ドキュメントから直接ルール関数を使用ないのはなぜですか。このような:

$('#newField0').rules('add', {
    required: true,
    minlength: 2
});
//use Html.ValidationMessage will renders a span element, unobtrusive need it to display errors
$('@Html.ValidationMessage("newField0")').insertAfter('#newField0');

2

上記の回答としてマークされたXhalentのソリューションから、私は少し拡張しました。

$.validator.unobtrusive.parseDynamicContent = function (selector) {
    var $selector = $(selector),
        $jqValUnob = $.validator.unobtrusive,
        selectorsDataValAttr = $selector.attr('data-val'),
        $validationInputs = $selector.find(':input[data-val=true]');

    if ((selectorsDataValAttr !== 'true') && 
        ($validationInputs.length === 0)) { 
        return; 
    }

    if (selectorsDataValAttr === 'true') {
        $jqValUnob.parseElement(selector, true);
    }

    $validationInputs.each(function () {
        $jqValUnob.parseElement(this, true);
    });

    //get the relevant form
    var $form = $selector.first().closest('form');

    $jqValUnob.syncValdators($form);
};

/* synchronizes the unobtrusive validation with jquery validator */
$.validator.unobtrusive.syncValdators = function ($form) {
    if ($.hasData($form[0])) {
        var unobtrusiveValidation = $form.data('unobtrusiveValidation'),
            validator = $form.validate();

        // add validation rules from unobtrusive to jquery
        $.each(unobtrusiveValidation.options.rules, function (elname, elrules) {
            if (validator.settings.rules[elname] == undefined) {
                var args = {};
                $.extend(args, elrules);
                args.messages = unobtrusiveValidation.options.messages[elname];
                $("[name='" + elname + "']").rules("add", args);
            } else {
                $.each(elrules, function (rulename, data) {
                    if (validator.settings.rules[elname][rulename] == undefined) {
                        var args = {};
                        args[rulename] = data;
                        args.messages = unobtrusiveValidation.options.messages[elname][rulename];
                        $("[name='" + elname + "']").rules("add", args);
                    }
                });
            }
        });
        // remove all validation rules from jquery that arn't in unobtrusive
        $.each(validator.settings.rules, function (elname, elrules) {
            if (unobtrusiveValidation.options.rules[elname] === undefined) {
                delete validator.settings.rules[elname];
            } else {
                $.each(elrules, function (rulename, data) {
                    if (rulename !== "messages" && unobtrusiveValidation.options.rules[elname][rulename] === undefined) {
                        delete validator.settings.rules[elname][rulename];
                    }
                });
            }
        });
    }        
};

$.validator.unobtrusive.unparseContent = function (selector) {
    var $selector = $(selector);

    // if its  a text node, then exit
    if ($selector && $selector.length > 0 && $selector[0].nodeType === 3) {
        return;
    }

    var $form = $selector.first().closest('form'), 
        unobtrusiveValidation = $form.data('unobtrusiveValidation');

    $selector.find(":input[data-val=true]").each(function () {
        removeValidation($(this), unobtrusiveValidation);
    });
    if ($selector.attr('data-val') === 'true') {
        removeValidation($selector, unobtrusiveValidation);
    }
    $.validator.unobtrusive.syncValdators($form);
};

function removeValidation($element, unobtrusiveValidation) {
    var elname = $element.attr('name');
    if (elname !== undefined) {
        $element.rules('remove');
        if (unobtrusiveValidation) {
            if (unobtrusiveValidation.options.rules[elname]) {
                delete unobtrusiveValidation.options.rules[elname];
            }
            if (unobtrusiveValidation.options.messages[elname]) {
                delete unobtrusiveValidation.options.messages[elname];
            }
        }
    }
}

したがって、基本的には上記のXhalentのソリューションと同じように機能しますが、DOMから削除する要素のルールを削除する機能を追加しました。そのため、Domから要素を削除し、それらの検証ルールを削除する場合も、次を呼び出します。

$.validator.unobtrusive.unparseContent('input.something');

1

私のコードで@Xhalentのコードスクリプトを見つけ、それを使用していなかったために削除しようとしていたため、このSOの質問が表示されました。

このコードはかなりクリーンでシンプルです:

jQuery.fn.unobtrusiveValidationForceBind = function () {
    //If you try to parse a form that is already parsed it won't update
    var $form = this
       .removeData("validator") /* added by the raw jquery.validate plugin */
            .removeData("unobtrusiveValidation");  /* added by the jquery     unobtrusive plugin */

    $form.bindUnobtrusiveValidation();
}

次に、このjQuery拡張機能を呼び出すには、セレクターを使用してフォームを取得します。

$('#formStart').unobtrusiveValidationForceBind();

ビオラ!


1

私は気力の答えを試しました、そして最初はすべてがうまくいったようでした。しかししばらくすると、追加したアイテムを動的に使用すると、検証の速度が大幅に低下することに気付きました。その理由は、彼のソリューションではイベントハンドラーのバインドが解除されず、毎回新しいハンドラーが追加されるためです。したがって、5つのアイテムを追加すると、検証は1回だけではなく6回実行されます。これを修正するには、removeData呼び出しに加えてイベントをアンバインドする必要があります。

$("form").removeData("validator")
         .removeData("unobtrusiveValidation")
         .off("submit.validate click.validate focusin.validate focusout.validate keyup.validate invalid-form.validate");
$.validator.unobtrusive.parse("form");

1

動的コンテンツの場合、以下のように控えめな検証を更新しForm、送信中に有効かどうかを確認する必要があります。

function UpdateUnobtrusiveValidations(idForm) {
    $(idForm).removeData("validator").removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse($(idForm));
};


$('#idDivPage').on('click', '#idSave', function (e) {
    e.preventDefault();
    if (!$('#idForm').valid()) {
        // Form is invalid … so return
        return false;
    }
    else {
        // post data to server using ajax call
        // update Unobtrusive Validations again
        UpdateUnobtrusiveValidations('#idForm');
    }
});

0

私はしばらくこれをいじくり回して、解決策を破棄し、後でもう一度やり直しました(少し時間があるときは、信じられないかもしれません)。

このスレッドが最後に作成またはコメントされたため、jqueryの新しいバージョン(私たちは1.7.2を使用しています)でこの動作が変更されたかどうかはわかりません.parseElement(inputElement)が、動的に作成された要素をフォームに追加しようとするとうまく機能することがわかりました既にバリデーターがロードされています。これは上記のコメントの1つですでに@jamesfm(2011年2月15日)によって提案されましたが、これに取り組んでいた最初の数回は見落としました。したがって、それをより明確にするために別の回答として追加します。これは優れたソリューションであり、それほどオーバーヘッドを必要としないためです。後続の回答で提起されたすべての問題に関連するわけではないかもしれませんが、元の質問に対する解決策になると思います。これが私が私の仕事をする方法です:

//row & textarea created dynamically by an async ajax call further up in the code
var row = ...; //row reference from somewhere
var textarea = row.find("textarea");
textarea.val("[someValue]");

//add max length rule to the text area
textarea.rules('add', {
    maxlength: 2000
});
//parse the element to enable the validation on the dynamically added element
$.validator.unobtrusive.parseElement(textarea);

0

最初に、呼び出しは検証ではなく.validatorにする必要があると思います。フォームのIDを渡す必要があります。

$.validator.unobtrusive.parse("#id");

jquery.validateとjquery.validate.unobtrusiveスクリプトの両方をロードし、Html.EnableClientValidation()メソッドとHtml.EnableUnobtrusiveJavaScript()メソッドを呼び出したと思いますか?ベースページのコードサンプルと動的に読み込まれるフォームを投稿できますか?
Chris Allmark 2010

0

いくつかのエラーがすでに表示されている可能性があるものを追加および削除する必要がある場合は、これが付属しています。これは主に、この質問ページのさまざまなアイデアに基づいています。destroy()JQuery検証のデータ属性を単に削除する代わりに、組み込みを使用します。

function resetValidator($form: JQuery) {
    $form.validate().destroy();

    //reset unobtrusive validation summary, if it exists
    $form.find("[data-valmsg-summary=true]")
        .removeClass("validation-summary-errors")
        .addClass("validation-summary-valid")
        .find("ul").empty();

    //reset unobtrusive field level, if it exists
    $form.find("[data-valmsg-replace]")
        .removeClass("field-validation-error")
        .addClass("field-validation-valid")
        .empty();

    $form.removeData("unobtrusiveValidation");
}

フォームの入力を動的に変更する前に呼び出します。その後、検証を再初期化します。

resetValidator($form);
//add or remove inputs here ...
$.validator.unobtrusive.parse($form);

注:一部またはすべての入力が検証されてエラーが発生した場合、それらのエラーはリセットされます...しかし、次の検証で正しく戻されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.