jQuery Validate - Only allow one out of two

前端 未结 4 383
我在风中等你
我在风中等你 2021-01-14 07:37

Need a little help. So got a form, where I\'ve got two fields mobile and telephone. Only one is required. My code below does that, but what I would like is I don\'t want peo

相关标签:
4条回答
  • 2021-01-14 08:02

    Use required method with a dependency-espression (jquery selector), this case using a :blank pseudo selector that is part of the validate plugin

    $(form).validate({
       rules
       {
         mobile:{required: '#telephone:blank'}
         telephone:{required: '#mobile:blank'}
       }
    });
    

    from docs - 'Very often your expression will use selector filters such as #foo:checked, #foo:filled, #foo:visible. This plugin provides custom selectors for that purpose.'

    EDIT

    sorry, I didn't fully read the question. The closest method to what you need is the require_from_group method found in the additional-methods.js file of jQuery validate. You need a very minor tweak to test for exactly one validated field from your group.

    eg

    <form>
        <input class="productinfo" name="partnumber" />
         <input class="productinfo" name="description" />
         <input type="submit" />
    </form>
    

    with code

    jQuery.validator.addMethod("require_from_group_exact", function(value, element, options) {
        var validator = this;
        var selector = options[1];
        var validOrNot = $(selector, element.form).filter(function() {
            return validator.elementValue   (this);
        }).length == options[0];
    
        if(!$(element).data('being_validated')) {
            var fields = $(selector, element.form);
            fields.data('being_validated', true);
            fields.valid();
            fields.data('being_validated', false);
        }
        return validOrNot;
    }, jQuery.format("Please fill {0} of these fields."));
    
    $('form').validate({
        rules:{
        partnumber:  {require_from_group_exact: [1,".productinfo"]},
        description: {require_from_group_exact: [1,".productinfo"]}
        }
     });
    

    if you compare this to the original method in addtional-methods.js you will see it is almost the same.

    Hopefully this will help - you need to replace partnumber and description with 'telephone' and 'mobile' and you should be set.

    fiddle here

    0 讨论(0)
  • 2021-01-14 08:05

    From a quick read of the documentation, it looks like the validator's default methods are designed to operate on fields which have no knowledge of other fields. It might be neater to define your own:

    function XOR_value_validator(value, el, args) {
        var otherValue = $(args[0]).val();
        return (value && !otherValue) || (!value && otherValue);
    }
    
    jQuery.validator.addMethod(
        'XOR_with',
        XOR_value_validator,
        jQuery.validator.format('{1}')
    );
    

    And use something like:

    mobile : {
        XOR_with: [
            '#telephone', // assumed to be a jQuery selector for an element with a value()
            'Please enter either a telephone number or a mobile number.' // error message
        ]
    },
    telephone: {
        XOR_with: [
            '#mobile', // assumed to be a jQuery selector for an element with a value()
            'Please enter either a telephone number or a mobile number.' // error message
        ]
    }
    

    http://jqueryvalidation.org/jQuery.validator.addMethod

    This comes with no warranty! :P I wrote it completely untested (from the docs) in this text area.

    Edit:

    Regarding the comments:

    You could probably shoehorn in functionality to enable/disable form elements accordingly, if this code is continually executed as the user fills out the form. However, I would advise against that, since this part of your code should only really be concerned with validation and not UX.

    To extend the functionality for more than two fields (again, not tested) you might do:

    function one_field_allowed_validator(value, el, args) {
        var otherFields = args[0],
            valuesFound = value ? 1 : 0;
    
        for (var i = 0, limit = otherFields.length; i < limit; ++i) {
            var val = $(otherFields[i]).val();
            if (val && ++valuesFound === 2) {
                return false;
            }
        }
        return valuesFound !== 0;
    }
    
    jQuery.validator.addMethod(
        'Allow_one_with',
        one_field_allowed_validator,
        jQuery.validator.format('{1}')
    );
    

    Usage:

    mobile : {
        Allow_one_with: [
            ['#telephone', '#work'],
            'Please enter a telephone number, a mobile number or a work number.'
        ]
    },
    telephone: {
        Allow_one_with: [
            ['#mobile', '#work'],
            'Please enter a telephone number, a mobile number or a work number.'
        ]
    },
    work: {
        Allow_one_with: [
            ['#mobile', '#telephone']
            'Please enter a telephone number, a mobile number or a work number.'
        ]
    }
    

    It's feeling pretty hacky now! With every additional field in your Allow_one_with group, you must update all existing Allow_one_with validations (to include the new field and probably a new error message). I would be reluctant to use my method for more than the XOR.

    0 讨论(0)
  • 2021-01-14 08:10

    You could keep a variable with the amount of validated items:

    validatedItems : 0,
    
    mobile : {
        var self = this;
        required: function(element) {  
            if ($("#telephone").val().length > 0) {
                self.validatedItems--;
                return false;
            }
            else {
            self.validatedItems++;
                return true;
            }
        }
    },                                               
    telephone: {
        var self = this;
        required: function(element) {
            if ($("#mobile").val().length > 0) {
                self.validatedItems--;
                 return false;
             }
             else {
                self.validatedItems++;
                return true;
            }
        }
    },
    

    And then you could check if one or more items are validated when you send the form:

    if( validatedItems > 0 ) {
        sendForm();
    }
    
    0 讨论(0)
  • 2021-01-14 08:14

    This solution uses standard functionality from the Validation plugin. I used the require_from_group rule to make sure at least one is filled, and then I used the maxlength rule to disallow one if the other is filled. Just make sure the phone-group class is added to both input fields to support the require_from_group rule.

    $("form").validate({
        rules: {
            mobile: {
                require_from_group: [1, ".phone-group"], 
                maxlength: {param: 0, depends: "#telephone:filled"}
            },
            telephone: {
                require_from_group: [1, ".phone-group"], 
                maxlength: {param: 0, depends: "#mobile:filled"}
            }
        },
        messages: {
            mobile: "Please enter either a telephone number or a mobile number.",
            telephone: "Please enter either a telephone number or a mobile number."
        }
    });
    
    0 讨论(0)
提交回复
热议问题