开发者

jQuery Validation - Changing "Required" Attribute based on other fields

I'm using the jQuery Validation plugin (http://docs.jquery.com/Plugins/Validation) on a form I'm building. The form is made up of 6 fieldsets, each containing 3 text inputs for an email address, a first name and a last name. A simplified version of the markup is like so:

<form id="ref" action="submit.php" method="post">
    <fieldset id="ref_1">
        <input id="ref_1_email" type="text" />
        <input id="ref_1_fname" type="text" />
        <input id="ref_1_lname" type="text" />
    </fieldset>
    <fieldset id="ref_2">
        <input id="ref_2_email" type="text" />
        <input id="ref_2_fname" type="text" />
        <input id="ref_2_lname" type="text" />
    </fieldset>
    <fieldset id="ref_3">
        <input id="ref_3_email" type="text" />
        <input id="ref_3_fname" type="text" />
        <input id="ref_3_lname" type="text" />
    </fieldset>
</form>

and so forth, up to ref_6. However, the user does not necessarily need to complete every field - they may only choose to fill in the inputs inside fieldset#ref_1 and fieldset#ref_2, and leave the others blank. But if they enter, for example, an email for ref_1, a first and last name for ref_1 would be required also. So what I need to do is check all 3 inputs in a fieldset. If they are all blank, they can be ignored, however if one of the inputs is filled in, it's two neighbours must be completed also. All my attempts so far have been very cumbersome (watching for a change on each one and then evaluating to see if empty...), any help would be greatly, greatly appreciated.

Thanks

Update:

I found a post with a similar issue, with the suggested solution being:

$('开发者_Python百科#emailToName2').keyup(function () {
    $('#emailToAddress2').toggleClass('required', $(this).val());
});

But that requires the above logic duplicated for each and every input, which seems like overkill to me. What would be a more dynamic approach?

Cheers!


You can specify an expression or callback when indicating that a field is required. The validation plugin will then evaluate the expression or callback before validating the field.

Here's an example:

$("#ref").validate({
  rules: {
    ref_1_email: {
      required: function(element) {
        return $("#ref_1_fname").val() || $("ref_1_lname").val();
      }
    }
  }
});
$("#ref_1_email").blur(function() {
  $("#ref_1_fname").valid();
  $("#ref_1_lname").valid();
});

There's probably some refactoring that you can do so that you don't have to repeat all of this for each field...


You can write your own custom validation class that evaluates if the other either of the 2 inputs have been completed.

eg.

jQuery.validator.addMethod('MyOwnValidator', function(value, element) {
    var required = false;
    $(element).parent().children('input').each(function() {
       if($(this).val() && $(this).attr('id') != $(element).attr('id')){
           required = true;
       }
    });
    return !required;
});

This will evaluate if any of the sibling inputs have a value and if they do it makes the calling input required.


Not tried and neither properly written:

$("#ref input").keyup(function () {
 $(this).parents("fieldset").children("input").toggleClass("required", $(this).val());
});


You cant do it all in one loop, since you need to check siblings before toggling the class. You can, however, define a small loop function that can check and apply, but you will need to call it several times to maintain logic.

Try this:

var loop = function(target, fn) {
    var t = 0, fn = fn || function(){};
    $(target).siblings().andSelf().each(function(i, el) {
        t += $(el).val().length;
        fn(el);
    });
    return t;
}
$('fieldset input').each(function() {
    $(this).bind('blur', function(e) {
        if(loop(e.target)) {
            loop(e.target, function(el) {
                $(el).toggleClass('required', !$(el).val().length);
            })
        } else {
            loop(e.target, function(el) {
                $(el).removeClass('required');
            })
        }
    });
});


Was just investigating this for a project. According to the docs, the following should do what you want.

When first calling validate on your form, do it like this:

$("#emailRecsForm").validate({
   rules: {
       ref_1_email: {
         required: ("#ref_1_fname:filled" || "#ref_1_lname:filled"),
         email: true
       },
       ref_1_fname: {
         required: ("#ref_1_email:filled" || "#ref_1_lname:filled")
       },
       ref_1_lname: {
         required: ("#ref_1_email:filled" || "#ref_1_fname:filled")
       },

       ref_2_email: {
         required: ("#ref_2_fname:filled" || "#ref_2_lname:filled"),
         email: true
       },
       // And so on...
   }
});

Also, make sure each of your inputs has a name attribute identical to its id.

I haven't actually tried it myself, but judging by the docs (see required(dependency-expression)), it should work.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜