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

우수한 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 유효성 검사추가되었습니다 .



답변

그것은 훌륭한 솔루션 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 파일을 포함하는 것을 잊지 마십시오!


답변

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

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


답변

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

또한 모든 필드가 아닌 별도의 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;(!)"));


답변

현재 버전이하는 문제로 고통받지 않는 패치 를 제출했습니다 ( “필수”옵션이 다른 필드에서 제대로 작동하지 않는 경우, 현재 버전의 문제에 대한 토론은 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."));


답변

$로 변수 이름을 시작하는 것은 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(...)

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

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

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


답변

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

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

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

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

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


답변

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."));

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