51

同じ名前の入力フィールドを持つ動的に生成されたフォームがあります (例: "map")。フォーム ハンドラー コード (Perl/CGI) は入力値の配列 (この場合は ) を処理するように設計されているため、フィールド名を変更したり、一意のフィールド名を生成したりするオプションはありません@map

このような状況で JQuery Validate Pluginを使用してフォームを検証するにはどうすればよいですか? 具体的には、送信された配列の 1 つの要素に特定の固定値を持たせたいと考えています。serializeArray()現在、JSON オブジェクトを作成し、それをトラバースして条件が満たされていることを確認するカスタム イベント ハンドラーを使用しています。しかし、アプリケーションの残りの部分で Validate プラグインを使用したので、ここでも同じプラグインを使用してそのようなケースを処理できるかどうか疑問に思っていました。

ご清聴ありがとうございました。

4

12 に答える 12

71

ソース ファイル jquery.validation を変更する代わりに、必要なページでのみ編集する必要がある関数を単純にオーバーライドできます。

例は次のとおりです。

$.validator.prototype.checkForm = function() {
    //overriden in a specific page
    this.prepareForm();
    for (var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++) {
        if (this.findByName(elements[i].name).length !== undefined && this.findByName(elements[i].name).length > 1) {
            for (var cnt = 0; cnt < this.findByName(elements[i].name).length; cnt++) {
                this.check(this.findByName(elements[i].name)[cnt]);
            }
        } else {
            this.check(elements[i]);
        }
    }
    return this.valid();
};

これは最善の解決策ではないかもしれませんが、少なくとも新しいバージョンがリリースされたときに後で置き換えられる可能性のあるソース ファイルを編集する必要はありません。オーバーライドされた関数が壊れるかもしれないし、壊れないかもしれない場所。

于 2012-07-31T12:55:31.817 に答える
58

私は知っている古いスレッドですが、同じ問題の修正を探してそれに出くわしました。

より洗練されたソリューションがここに投稿されています: http ://web-funda.blogspot.com/2009/05/jquery-validation-for-array-of-input.html

jquery.validate.jsを編集し、checkFormを次のように変更するだけです。

    checkForm: function() {
    this.prepareForm();
    for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
        if (this.findByName( elements[i].name ).length != undefined && this.findByName( elements[i].name ).length > 1) {
            for (var cnt = 0; cnt < this.findByName( elements[i].name ).length; cnt++) {
                    this.check( this.findByName( elements[i].name )[cnt] );
            }
        } else {
            this.check( elements[i] );
        }
    }
    return this.valid();
}
于 2010-11-09T17:11:59.333 に答える
43

最後に、複数のフィールドで検証を行う最も簡単な方法を試したとき、さまざまなことを検索して試すことに時間を費やしました。各フィールドとそのクローンは、各セットに固有のクラスを共有します。そのクラスを使用して入力をループし、通常どおり検証ルールを追加しました。これが他の誰かに役立つことを願っています。

    $("#submit").click(function(){
    $("input.years").each(function(){
        $(this).rules("add", {
            required: true,
            messages: {
                required: "Specify the years you worked"
            }
        } );            
    });

    $("input.employerName").each(function(){
        $(this).rules("add", {
            required: true,
            messages: {
                required: "Specify the employer name"
            }
        } );            
    }); 

    $("input.employerPhone").each(function(){
        $(this).rules("add", {
            required: true,
            minlength: 10,
            messages: {
                required: "Specify the employer phone number",
                minlength: "Not long enough"
            }
        } );            
    }); 

    $("input.position").each(function(){
        $(this).rules("add", {
            required: true,
            messages: {
                required: "Specify your position"
            }
        } );            
    });             

    $("input.referenceName").each(function(){
        $(this).rules("add", {
            required: true,
            messages: {
                required: "Specify the reference name"
            }
        } );            
    });         

    $("input.referencePhone").each(function(){
        $(this).rules("add", {
            required: true,
            minlength: 10,
            messages: {
                required: "Specify your reference phone number",
                minlength: "Not long enough"
            }
        } );            
    });

// Now do your normal validation here, but don't assign rules/messages for the fields we just set them for





});
于 2009-08-06T02:12:48.863 に答える
11

プラグインの作成者である Jörn Zaefferer のメールから、検証ではラジオ ボタンとチェック ボックスを除いてフィールド名が一意である必要があることを知りました。

于 2009-06-01T04:47:03.283 に答える
5

ジェイソンの答えはそのトリックを行いますが、これを行ったすべてのフォームに余分なクリックイベントを追加したくありませんでした.

私の場合、フィールド名が同じであっても、「[]」で終わる名前を検証プラグインに異なるものと見なさせます。これを行うために、jquery.validate.js の読み込み後にこれら 2 つの内部メソッドを上書きしました。

$.validator.prototype.elements= function() {
var validator = this,
    rulesCache = {};

// select all valid inputs inside the form (no submit or reset buttons)
// workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
return $([]).add(this.currentForm.elements)
.filter(":input")
.not(":submit, :reset, :image, [disabled]")
.not( this.settings.ignore )
.filter(function() {
    !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);

    // select only the first element for each name (EXCEPT elements that end in []), and only those with rules specified
    if ( (!this.name.match(/\[\]/gi) && this.name in rulesCache) || !validator.objectLength($(this).rules()) )
        return false;

    rulesCache[this.name] = true;
    return true;
});
};


$.validator.prototype.idOrName = function(element) {

// Special edit to get fields that end with [], since there are several [] we want to disambiguate them
// Make an id on the fly if the element doesnt have one
if(element.name.match(/\[\]/gi)) {
    if(element.id){
        return element.id;
    } else {
        var unique_id = new Date().getTime();

        element.id = new Date().getTime();

        return element.id;
    }
}

return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
};
于 2011-03-31T15:17:50.140 に答える
3

これが私がやった方法です。以前に提案された方法よりも少し簡単です。

function validateTab(tab) {
    var valid = true;
    $(tab).find('input').each(function (index, elem) {
        var isElemValid = $("#registrationForm").validate().element(elem);
        if (isElemValid != null) { //this covers elements that have no validation rule
            valid = valid & isElemValid;
        }
    });

    return valid;
}

私の場合、すべてのフィールドを一度に検証したくないため、ウィザード (3 つのステップ) がさらに複雑になることがわかりました。基本的にコンポーネントをタブに配置し、最初のタブが有効な場合は、最後のタブに到達するまで次のタブに移動し、その後すべてのデータを送信します。したがって、tabそこにあるパラメーターは実際のタブ要素です (これは ですdiv)。次に、すべての入力要素の子をタブにループし、それらの有効性をチェックします。

それ以外は標準です。


完全を期すために、コードの残りの部分を次に示します。フォームの送信がどのように行われ、バリデータがどのように見えるかを示します。

<a href="javascript:moveToNextTab(1)" class="button next">Submit</a>

そして、ここで呼び出された js 関数:

function moveToNextTab(currentTab) {
    var tabs = document.getElementsByClassName("tab");
    //loop through tabs and validate the current one.
    //If valid, hide current tab and make next one visible.
}

これらの検証ルールを使用しています (JQuery.ready で作成します):

$("#registrationForm").validate({
    rules: {
        birthdate: {
            required: true,
            date: true
        },
        name: "required",
        surname: "required",
        address: "required",
        postalCode: "required",
        city: "required",
        country: "required",
        email: {
            required: true,
            email: true
        }
    }
});
于 2012-01-17T16:12:26.337 に答える
3

「jQuery検証プラグイン1.7」を使用しています。

同じ名前の複数の「$(:input)」要素が検証されない問題

$.validator.element メソッドです。

elements: function() {
        var validator = this,
            rulesCache = {};

        // select all valid inputs inside the form (no submit or reset buttons)
        // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
        return $([]).add(this.currentForm.elements)
        .filter(":input")
        .not(":submit, :reset, :image, [disabled]")
        .not( this.settings.ignore )
        .filter(function() {
            !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);

            // select only the first element for each name, and only those with rules specified
            if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
                return false;

            rulesCache[this.name] = true;
            return true;
        });
    },

条件

if ( rulesCache の this.name ||.....

同じ名前を共有する 2 番目以降の要素を評価 true....

解決策は、次の条件を持つことです。

(this.id || this.name) in rulesCache

すみません、JS ピューリタンの皆さん、(this.id || this.name) は 100% ではありません...

もちろん、

rulesCache[this.name] = true;

行も適切に変更する必要があります。

$.validator.prototype.elements メソッドは次のようになります。

$(function () {
if ($.validator) {
    //fix: when several input elements shares the same name, but has different id-ies....
    $.validator.prototype.elements = function () {

        var validator = this,
            rulesCache = {};

        // select all valid inputs inside the form (no submit or reset buttons)
        // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
        return $([]).add(this.currentForm.elements)
        .filter(":input")
        .not(":submit, :reset, :image, [disabled]")
        .not(this.settings.ignore)
        .filter(function () {
            var elementIdentification = this.id || this.name;

            !elementIdentification && validator.settings.debug && window.console && console.error("%o has no id nor name assigned", this);

            // select only the first element for each name, and only those with rules specified
            if (elementIdentification in rulesCache || !validator.objectLength($(this).rules()))
                return false;

            rulesCache[elementIdentification] = true;
            return true;
        });
    };
}

});

于 2011-06-28T19:29:32.660 に答える
3

入力の未使用の属性を使用して元の名前を保存し、インデックスを付けて名前を変更するだけです。

function addMultiInputNamingRules(form, field, rules){    
    $(form).find(field).each(function(index){
    $(this).attr('alt', $(this).attr('name'));
    $(this).attr('name', $(this).attr('name')+'-'+index);
    $(this).rules('add', rules);
});

}

function removeMultiInputNamingRules(form, field){    
    $(form).find(field).each(function(index){
    $(this).attr('name', $(this).attr('alt'));
    $(this).removeAttr('alt');
});

}

次に、バリデーターを設定した後:

addMultiInputNamingRules('#form-id', 'input[name="multifield[]"]', { required:true });

検証が終了したら、次のように元に戻します。

removeMultiInputNamingRules('#form-id', 'input[alt="multifield[]"]');

- お役に立てれば!

于 2010-10-19T20:05:25.710 に答える
1

多分私は要点を逃していますが、バリデーターは複数の名前で動作しないため (試してみました...失敗しました!)、名前を動的に変更するようにフォームを変更し、ルールを設定してから、送信時に名前の設定を解除しました。

2 つの方法 (wlog は無視して、コンソールに出力するだけです):

// convert the field names into generated ones to allow fields with the same names 
// to be validated individually. The original names are stored as data against the
// elements, ready to be replaced. The name is replaced with
// "multivalidate-<name>-<id>", e.g. original => 'multivalidate-original-1'

function setGeneratedNamesWithValidationRules(form, fields, rules) {

    var length = fields.length;

    for (var i=0; i < length; ++i ){
        var name = fields[i];

        var idCounter = 0;  
        // we match either the already converted generator names or the original
        $("form [name^='multivalidate-" + name + "'], form [name='" + name + "']").each(function() {
            // identify the real name, either from the stored value, or the actual name attribute
            var realName = $(this).data('realName');
            if (realName == undefined) {
                realName = $(this).attr("name");
                $(this).data('realName', realName);
            }

            wlog("Name: " + realName + " (actual: " + $(this).attr("name") + "), val: " + $(this).val() + ". Rules: " + rules[realName]);
            $(this).attr("name", "multivalidate-" + realName + "-" + idCounter);
            if (rules[realName]) {
                $(this).rules("add", rules[realName]);
            }
            idCounter++;
        });
    }
}

function revertGeneratedNames(form, fields) {

    var length = fields.length;

    for (var i=0; i < length; ++i ){
        var name = fields[i];
        wlog("look for fields names [" + name + "]");

        $("form [name^='multivalidate-" + name + "']").each(function() {
            var realName = $(this).data('realName');
            if (realName == undefined) {
                wlog("Error: field named [" + $(this).attr("name") + "] does not have a stored real name");
            } else {
                wlog("Convert [" + $(this).attr("name") + "] back to [" + realName + "]");
                $(this).attr("name", realName);
            }
        });
    }
}

フォームの読み込み時に、別の行を動的に追加するたびに、set メソッドを呼び出します。

setGeneratedNamesWithValidationRules($("#my-dynamic-form"), ['amounts'], { 'amounts': 'required'} );

これにより、名前が変更され、個別の検証が可能になります。

submitHandler: thingumy で、検証後に revert を呼び出します。

revertGeneratedNames(form, ['amounts']);

データを投稿する前に名前を元に戻します。

于 2010-10-19T11:57:20.800 に答える
1

私にとって、これはデバッグを無効にすることで非常に簡単に解決されました

 $("#_form").validate({
    debug:false,
    //debug: true,
    ...
    });
于 2015-04-05T10:00:05.657 に答える
-1

簡単な解決策があります:

$(document).ready(function() {
   $(".form").each(function() {
      $(this).validate({
         ...
         ,errorContainer: $(".status_mess",this) // use "this" as reference to that instance of form.
         ...
      });
   });
});
于 2011-09-19T07:15:14.170 に答える
-2

HTMLフォームの仕組みを誤解していると思います。1 つのデータ フィールドに対して 1 つまたは複数のオプションを選択できるようにする複数のチェックボックスとボタンを除き、すべてのフォーム要素には一意の名前が必要です。

あなたの場合、入力をデータ フィールドに割り当てることができないため、JQuery 検証だけでなく、サーバー側のフォーム バリデーターも失敗します。ユーザーに姓、名、電子メール アドレス、ファックス (オプション) を入力させ、すべての入力フィールドにname="map"

次に、送信時にこれらのリストを受け取ります。

map = ['Joe','Doe','joe.doeAThotmail.com','++22 20182238'] //All fields completed
map = ['Joe','Doe','joe.doeAThotmail.com'] //OK, all mandatory fields completed 
map = ['Doe', 'joe.doeAThotmail.com','++22 20182238']//user forgot prename, should yield error

このフォームを確実に検証することは不可能であることがわかります。

Perl フォーム ハンドラーのドキュメントを再確認するか、自分で作成した場合はそれを適応させることをお勧めします。

于 2009-06-02T15:50:13.710 に答える