jQuery Validate-그룹에서 하나 이상의 필드를 채워야합니다.


98

우수한 jQuery Validate Plugin 을 사용하여 일부 양식의 유효성을 검사하고 있습니다. 한 양식에서 사용자가 필드 그룹 중 하나 이상을 채우도록해야합니다. 꽤 좋은 해결책이 있다고 생각하고 공유하고 싶었습니다. 생각할 수있는 개선 사항을 제안하십시오.

이 작업을 수행하는 기본 제공 방법을 찾지 못한 채로 Rebecca Murphey의 사용자 지정 유효성 검사 방법을 검색하고 찾았습니다 . 이는 매우 유용했습니다.

나는 이것을 세 가지 방법으로 개선했습니다.

  1. 필드 그룹에 대한 선택기를 전달하려면
  2. 유효성 검사를 통과하기 위해 채워야하는 해당 그룹의 수를 지정하려면
  3. 그룹의 모든 입력이 유효성 검사를 통과하자마자 유효성 검사를 통과 한 것으로 표시합니다. ( 마지막 에 Nick Craver 에게 외침을 참조하십시오 .)

그래서 당신은 말할 수 있습니다 "선택기 Y와 일치하는 입력을 X 개 이상 채워야합니다." .

다음과 같은 마크 업이있는 최종 결과 :

<input class="productinfo" name="partnumber">
<input class="productinfo" name="description">

... 다음과 같은 규칙 그룹입니다.

// Both these inputs input will validate if 
// at least 1 input with class 'productinfo' is filled
partnumber: {
   require_from_group: [1,".productinfo"]
  }
description: {
   require_from_group: [1,".productinfo"]
}

항목 # 3은 .checked성공적인 유효성 검사시 오류 메시지에 의 클래스를 추가한다고 가정합니다 . 여기에 설명 된 대로 다음과 같이이 작업을 수행 할 수 있습니다 .

success: function(label) {  
        label.html(" ").addClass("checked"); 
}

위에 링크 된 데모에서와 같이 CSS를 사용 span.error하여 클래스가없는 경우 각각 의 X 이미지를 배경으로 제공합니다 ..checked 경우 체크 표시 이미지가 표시됩니다.

지금까지 내 코드는 다음과 같습니다.

jQuery.validator.addMethod("require_from_group", function(value, element, options) {
    var numberRequired = options[0];
    var selector = options[1];
    //Look for our selector within the parent form
    var validOrNot = $(selector, element.form).filter(function() {
         // Each field is kept if it has a value
         return $(this).val();
         // Set to true if there are enough, else to false
      }).length >= numberRequired;

    // The elegent part - this element needs to check the others that match the
    // selector, but we don't want to set off a feedback loop where each element
    // has to check each other element. It would be like:
    // Element 1: "I might be valid if you're valid. Are you?"
    // Element 2: "Let's see. I might be valid if YOU'RE valid. Are you?"
    // Element 1: "Let's see. I might be valid if YOU'RE valid. Are you?"
    // ...etc, until we get a "too much recursion" error.
    //
    // So instead we
    //  1) Flag all matching elements as 'currently being validated'
    //  using jQuery's .data()
    //  2) Re-run validation on each of them. Since the others are now
    //     flagged as being in the process, they will skip this section,
    //     and therefore won't turn around and validate everything else
    //  3) Once that's done, we remove the 'currently being validated' flag
    //     from all the elements
    if(!$(element).data('being_validated')) {
    var fields = $(selector, element.form);
    fields.data('being_validated', true);
    // .valid() means "validate using all applicable rules" (which 
    // includes this one)
    fields.valid();
    fields.data('being_validated', false);
    }
    return validOrNot;
    // {0} below is the 0th item in the options field
    }, jQuery.format("Please fill out at least {0} of these fields."));

만세!

외쳐

이제 그 외침을 위해-원래 내 코드는 다시 확인하는 대신 다른 일치하는 필드에 오류 메시지를 맹목적으로 숨겼습니다. 즉, 다른 문제가있는 경우 ( '숫자 만 허용되고 문자를 입력했습니다') , 사용자가 제출을 시도 할 때까지 숨겨졌습니다. 위의 주석에서 언급 한 피드백 루프를 피하는 방법을 몰랐기 때문입니다. 나는 방법이 있어야한다는 것을 알았 기 때문에 질문 을했고 Nick Craver가 나를 깨달았다 . 고마워, 닉!

해결 된 질문

이것은 원래 "이것을 공유하고 누구든지 개선을 제안 할 수 있는지 보자"와 같은 종류의 질문이었습니다. 여전히 피드백을 환영하지만이 시점에서 꽤 완벽하다고 생각합니다. (더 짧을 수도 있지만, 읽기 쉽고 간결하지 않기를 바랍니다.) 그러니 즐기세요!

업데이트-이제 jQuery 유효성 검사의 일부

이것은 공식적 으로 2012 년 4 월 3 일에 jQuery 유효성 검사추가되었습니다 .


또한 밀접하게 관련된 규칙을 참조하십시오.- "이 필드를 건너 뛰거나 최소한 X 필드를 채우십시오" -stackoverflow.com/questions/1888976/…
Nathan Long

하나의 임의 입력이 다른 입력이 채워 졌는지 확인하는 이유는 무엇입니까? 이건 말이 안 돼. 관련된 요소에 약간의 마크 업을 포함 할 수 있습니까?
몬트리올리스트

@dalbaeb-예제를 약간 명확히했습니다. 하나의 임의 입력이 다른 입력을 확인하는 것은 아닙니다. 그룹의 각 입력은 다른 모든 입력을 확인해야합니다.
Nathan Long

그렇게 생각했습니다. 정말 감사합니다!
몬트리올

3
감사합니다. 이것은 저에게 효과적이지만 양식의 다른 필수 필드는 확인 후 초점을 얻거나 잃지 않는 한 더 이상 응답하지 않습니다. (누군가이 질문을 다른 질문에 대한 답변으로 추가했지만 답변이 아니기 때문에 신고해야했습니다).
mydoghasworms 2011 년

답변:


21

그것은 훌륭한 솔루션 Nathan입니다. 감사합니다.

내가 한 것처럼 누군가가 그것을 통합하는 데 문제가 발생하는 경우 위의 코드를 작동시키는 방법은 다음과 같습니다.

additional-methods.js 파일 내부의 코드 :

jQuery.validator.addMethod("require_from_group", function(value, element, options) {
...// Nathan's code without any changes
}, jQuery.format("Please fill out at least {0} of these fields."));

// "filone" is the class we will use for the input elements at this example
jQuery.validator.addClassRules("fillone", {
    require_from_group: [1,".fillone"]
});

html 파일 내부의 코드 :

<input id="field1" class="fillone" type="text" value="" name="field1" />
<input id="field2" class="fillone" type="text" value="" name="field2" />
<input id="field3" class="fillone" type="text" value="" name="field3" />
<input id="field4" class="fillone" type="text" value="" name="field4" />

additional-methods.js 파일을 포함하는 것을 잊지 마십시오!


도움이되어 기쁘고 정보를 제공해 주셔서 감사합니다. 그러나 addClassRules 메서드를 수행하는 대신 각 개별 양식에 규칙 배열을 사용하는 것을 선호합니다. 이 페이지 ( jquery.bassistance.de/validate/demo/milk ) 로 이동하여 "이 페이지에서 사용 된 스크립트 표시"를 클릭하면 예제가 표시됩니다. 한 단계 더 나아가서 "rules"라는 배열을 선언 한 다음 별도로 var validator = $ ( '# formtovalidate'). validate (rules);
Nathan Long

또 다른 생각 : 여기서 보여주는 'fillone'클래스는 문제가 될 수 있습니다. 동일한 양식에서 하나 이상의 부품 번호와 하나 이상의 연락처 이름이 필요한 경우 어떻게해야합니까? 규칙은 부품 번호가 하나 이상있는 한 0 개의 연락처 이름을 허용합니다. 나는 그것이 같은 일련의 규칙에 더 나은 생각 require_from_group: [1,".partnumber"]...[1,".contactname"]올바른 일을 검증하고 확인하기 위해.
Nathan Long

6

좋은 솔루션입니다. 그러나 다른 필수 규칙이 작동하지 않는 문제가있었습니다. 양식에 대해 .valid ()를 실행하면이 문제가 해결되었습니다.

if(!$(element).data('being_validated')) {
  var fields = $(selector, element.form);
  fields.data('being_validated', true); 
  $(element.form).valid();
  fields.data('being_validated', false);
}

1
감사합니다 Sean, 저도이 문제를 겪고있었습니다. 하지만이 솔루션에는 한 가지 문제가 있습니다. 사용자가 처음으로 양식에 도달하면 첫 번째 그룹에서 요구 필드를 채우는 즉시 다른 모든 양식 필드의 유효성이 검사되어 결함이있는 것으로 표시됩니다. 이 문제를 해결 한 방법은 유효성 검사기의 인스턴스를 만들기 전에 form.submit () 핸들러를 추가하는 것이 었는데, 여기에서 flag를 설정했습니다 validator.formSubmit = true. 그룹에서 필요로하는 방법에서 해당 플래그를 확인합니다. 거기 있으면 내가하고 $(element.form).valid();, 그렇지 않으면 내가 해요 fields.valid();.
크리스토프

아무도 여기서 실제로 무슨 일이 일어나고 있는지 설명 할 수 있습니까? 저에게는 효과가 있었지만 재 검증 문제를 해결하지 않은 상당히 유사한 규칙이 있습니다 (그룹의 다른 필드는 여전히 유효하지 않은 것으로 표시됨). 그러나 지금은 유효하지 않은 경우에도 양식이 제출되는 것을 경험하고 있습니다. 그룹화 된 필드가 유효하면 제출 처리기를 입력하지 않고 유효하지 않으면 invalidHandler에 입력하지만 어쨌든 제출합니다! 이것이 유효성 검사 플러그인에서 상당히 심각한 버그라고 말하고 싶습니다. 규칙이 유효 함을 반환한다는 것은 해당 규칙에만 적용되며 (전체 필드도 아님) 잘못된 양식이 제출되는 이유는 무엇입니까?
Adam

나는 더 조사했고 proeprly를 검증하지 않는 그룹 이전의 필드입니다. 나는 이것을 별도의 질문으로 물었습니다 (부분적인 해결 방법과 함께) : stackoverflow.com/questions/12690898/…
Adam

4

숀 감사합니다. 다른 규칙을 무시하는 코드와 관련된 문제가 해결되었습니다.

또한 모든 필드가 아닌 별도의 div에 '적어도 하나의 필드를 입력하십시오 ..'메시지가 표시되도록 몇 가지 변경 사항을 적용했습니다.

양식 유효성 검사 스크립트에 넣어

showErrors: function(errorMap, errorList){
            $("#form_error").html("Please fill out at least 1 field before submitting.");
            this.defaultShowErrors();
        },

페이지 어딘가에 추가

<div class="error" id="form_error"></div>

require_from_group 메소드 addMethod 함수에 추가

 if(validOrNot){
    $("#form_error").hide();
}else{
    $("#form_error").show();
}
......
}, jQuery.format(" &nbsp;(!)"));

4

현재 버전이하는 문제로 고통받지 않는 패치 를 제출했습니다 ( "필수"옵션이 다른 필드에서 제대로 작동하지 않는 경우, 현재 버전의 문제에 대한 토론은 github에 있습니다.).

http://jsfiddle.net/f887W/10/의

jQuery.validator.addMethod("require_from_group", function (value, element, options) {
var validator = this;
var minRequired = options[0];
var selector = options[1];
var validOrNot = jQuery(selector, element.form).filter(function () {
    return validator.elementValue(this);
}).length >= minRequired;

// remove all events in namespace require_from_group
jQuery(selector, element.form).off('.require_from_group');

//add the required events to trigger revalidation if setting is enabled in the validator
if (this.settings.onkeyup) {
    jQuery(selector, element.form).on({
        'keyup.require_from_group': function (e) {
            jQuery(selector, element.form).valid();
        }
    });
}

if (this.settings.onfocusin) {
    jQuery(selector, element.form).on({
        'focusin.require_from_group': function (e) {
            jQuery(selector, element.form).valid();
        }
    });
}

if (this.settings.click) {
    jQuery(selector, element.form).on({
        'click.require_from_group': function (e) {
            jQuery(selector, element.form).valid();
        }
    });
}

if (this.settings.onfocusout) {
    jQuery(selector, element.form).on({
        'focusout.require_from_group': function (e) {
            jQuery(selector, element.form).valid();
        }
    });
}

return validOrNot;
}, jQuery.format("Please fill at least {0} of these fields."));

3

$로 변수 이름을 시작하는 것은 PHP에서는 필요하지만 Javascript에서는 상당히 이상합니다 (IMHO). 또한 "$ module"은 두 번, "module"은 한 번 언급하시는 것 같습니다. 이 코드는 작동하지 않는 것 같습니다.

또한 일반적인 jQuery 플러그인 구문인지 확실하지 않지만 addMethod 호출 위에 주석을 추가하여 수행 한 작업을 설명 할 수 있습니다. 위의 텍스트 설명이 있어도 어떤 fieldset, : filled, value, element 또는 selector가 참조하는지 잘 모르기 때문에 코드를 따르기가 어렵습니다. 아마도 이것의 대부분은 Validate 플러그인에 익숙한 사람에게 명백하므로 올바른 설명이 무엇인지 판단하십시오.

아마도 코드를 자체 문서화하기 위해 몇 가지 변수를 분리 할 수 ​​있습니다. 처럼,

var atLeastOneFilled = module.find(...).length > 0;
if (atLeastOneFilled) {
  var stillMarkedWithErrors = module.find(...).next(...).not(...);
  stillMarkedWithErrors.text("").addClass(...)

(이 코드 덩어리의 의미를 이해했다고 가정하면! :))

"모듈"이 무엇을 의미하는지 정확히 모르겠습니다.이 변수에 더 구체적인 이름을 지정할 수 있습니까?

전반적으로 좋은 코드입니다!


제안 해 주셔서 감사합니다. 변수 이름을 명확히하고 코드를 좀 더 읽기 쉽게 분류했습니다.
Nathan Long

2

작업중인 양식에는 다음과 같은 그룹화 된 입력이있는 여러 복제 영역이 있기 때문에 addMethod 함수의 정확히 한 줄을 변경하여 require_from_group 생성자에 추가 인수를 전달했습니다.

var commonParent = $(element).parents(options[2]);

이렇게하면 선택자, ID 또는 요소 이름을 한 번 전달할 수 있습니다.

jQuery.validator.addClassRules("reqgrp", {require_from_group: [1, ".reqgrp", 'fieldset']});

유효성 검사기는 양식의 모든 .reqgrp 클래스 요소를 계산하려고 시도하지 않고 각 필드 집합 내에서만 해당 클래스가있는 요소로 유효성 검사를 제한합니다.


2

Rocket Hazmat의 답변에 대한 내 균열은 유효성 검사가 필요한 다른 정의 된 필드 문제를 해결하려고 노력하지만 성공적으로 채울 때 모든 필드를 유효한 것으로 표시합니다.

jQuery.validator.addMethod("require_from_group", function(value, element, options){
    var numberRequired = options[0],
    selector = options[1],
    $fields = $(selector, element.form),
    validOrNot = $fields.filter(function() {
        return $(this).val();
    }).length >= numberRequired,
    validator = this;
    if(!$(element).data('being_validated')) {
        $fields.data('being_validated', true).each(function(){
            validator.valid(this);
        }).data('being_validated', false);
    }
    if (validOrNot) {
    $(selector).each(function() {
            $(this).removeClass('error');
            $('label.error[for='+$(this).attr('id')+']').remove();
        });
    }
    return validOrNot;
}, jQuery.format("Please fill out at least {0} of these fields."));

이제 남은 문제는 필드가 비어있다가 채운 다음 다시 비어있는 경우입니다.이 경우 오류는 그룹이 아닌 단일 필드에 적용됩니다. 그러나 그것은 어떤 빈도로도 일어날 가능성이 거의없는 것처럼 보이며이 경우에도 여전히 기술적으로 작동합니다.


이 방법 / 규칙이 2012 년 4 월에 플러그인에 통합 되었기 때문에이 답변에는 의미가 없습니다.
Sparky

Rocket Hazmat이 현재 유효성 검사기와 함께 제공되는 방법과 동일한 문제가 있습니다. 한 필드 그룹의 유효성을 검사하지만 다른 방법을 사용하는 다른 필드는 유효성이 검사되지 않습니다. 이 답변은 그 문제를 해결하려는 시도입니다. 더 나은 솔루션이 있으면 알려주십시오.
squarecandy 2013 년

개발자가 영구적으로 혼란에 문제보다는 추가가 해결 될 때까지, 나는 단순히 여기에 승인되고 일시적 어떤 솔루션을 추천 : github.com/jzaefferer/jquery-validation/issues/412
스파키

1

이것과 관련하여 확인되지 않는 다른 규칙에 문제가있어서 변경했습니다.

fields.valid();

이에:

var validator = this;
fields.each(function(){
   validator.valid(this);
});

또한 몇 가지 (개인적인) 개선 사항을 적용했으며 이것이 제가 사용중인 버전입니다.

jQuery.validator.addMethod("require_from_group", function(value, element, options){
    var numberRequired = options[0],
    selector = options[1],
    $fields = $(selector, element.form),
    validOrNot = $fields.filter(function() {
        return $(this).val();
    }).length >= numberRequired,
    validator = this;
    if(!$(element).data('being_validated')) {
        $fields.data('being_validated', true).each(function(){
            validator.valid(this);
        }).data('being_validated', false);
    }
    return validOrNot;
}, jQuery.format("Please fill out at least {0} of these fields."));

다른 필드의 유효성을 다시 확인하도록 작업하지만 이제 그룹의 모든 필드가 유효하지 않은 것으로 표시되고 하나를 입력하면 해당 필드 만 유효성이 검사됩니다. 적어도 나에게는?
크리스토프

@Chris-이것을 기반으로 한 나의 새로운 답변을보고 이것을 해결하십시오.
squarecandy 2013

0

고마워, 네이선. 당신은 저에게 많은 시간을 절약했습니다.

그러나이 규칙이 jQuery.noConflict () 준비가되어 있지 않다는 것을 알아야합니다. 따라서 모든 $를 jQuery로 바꿔야합니다.var $j = jQuery.noConflict()

그리고 질문이 있습니다. 기본 제공 규칙처럼 작동하도록하려면 어떻게해야합니까? 예를 들어, 이메일을 입력하면 "유효한 이메일을 입력하십시오"라는 메시지가 자동으로 사라지지만 그룹 필드 중 하나를 채우면 오류 메시지가 유지됩니다.


당신 말이 맞아요-나는 무 충돌 상황을 고려하지 않았습니다. 나중에 업데이트 할 수 있지만 원하는 경우 찾기 및 바꾸기를 쉽게 수행 할 수 있습니다. 두 번째 질문에 대해 동일한 문제가 보이지 않습니다. 빠른 테스트를 사용하면 그룹의 한 필드가 필요한 경우 입력하는 즉시 전체 그룹이 해당 규칙을 통과합니다. 두 개 이상이 필요한 경우 마지막 필수 항목이 채워지고 초점을 잃는 즉시 전체 그룹이 통과합니다. 당신이 보는 것입니까?
Nathan Long

흠 어떤 이유로 마크 업이 망가졌고 나는 그것을 고치는 데 성공하지 못했습니다
Rinat

Rinat-문제를 단순화하고 좁힐 수 있습니까? noconflict 변경이 필요하지 않은 더 간단한 양식에서 내 코드를 사용해보십시오. 테스트 할 수있는 가장 간단한 양식을 수행하고 먼저 작동하도록하십시오.
Nathan Long
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.