JQuery Validation plugin – validate group of input fields and at least one group is required

jquery, jquery-validate

I am trying to validate my form with jQuery Validate Plugin.
My form require at least one pair of this input (ex: mobilePhone/mobilePhone_p or/and personalPhone/personalPhone_p or/and workPhone/workPhone_p)
but I don't know how to link one text field (phone number) with his associated radio button (preferred yes/no) for validating my form and validate there is at least one pair.
If one or multiple pair is set, my form also require at least one checked radio button.

HTML form:

<form method="post" action="#" id="phoneForm">    <table>        <tr>            <td><label for="mobilePhone">Mobile</label></td>            <td>                <input type="text" class="mp_phone" name="mobilePhone" id="mobilePhone" value="" />            </td>            <td><label for="mobilePhone_p">Preferred phone number</label> <input type="radio" name="num_p" id="mobilePhone_p" value="mobilePhone_p" /></td>        </tr>        <tr>            <td><label for="personalPhone">Personal</label></td>            <td>                <input type="text" class="mp_phone" name="personalPhone" id="personalPhone" value="" />            </td>            <td><label for="personalPhone_p">Preferred phone number</label> <input type="radio" name="num_p" id="personalPhone_p" value="personalPhone_p" /></td>        </tr>        <tr>            <td><label for="workPhone">Work</label></td>            <td>                <input type="text" class="mp_phone" name="workPhone" id="workPhone" value="" />            </td>            <td><label for="workPhone_p">Preferred phone number</label> <input type="radio" name="num_p" id="workPhone_p" value="workPhone_p" /></td>        </tr>    </table>    <button type="submit" id="validateFormButton">Submit</button></form>

jQuery Validate :

$("#phoneForm").validate({    rules: {        mobilePhone: {            phone: true,            require_from_group: [1,".mp_phone"]        },        personalPhone: {            phone: true,            require_from_group: [1,".mp_phone"]        },        workPhone: {            phone: true,            require_from_group: [1,".mp_phone"]        },        num_p: {            required: true        }    }   });

(phone is a custom method to validate phone number and require_from_group is defined in http://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/additional-methods.js)

It's works when fields require at least one text field but radio button groups is not validated when require_from_group is set on other fields…

How can I validate my form using jQuery Validation plugin ?

Best Solution

I found a solution by customizing require_from_group method (based on Jquery .validate require_from_group) :

jQuery.validator.addMethod("require_from_group_with_radio", function(value, element, options) {    var numberRequired = options[0];    var selector = options[1];    var fields = jQuery(selector, element.form);    var filled_fields = fields.filter(function() {        // check if not empty and radio is checked        return jQuery(this).val() !== "" && jQuery(this).closest("tr").find("input:radio").is(":checked");     });    var empty_fields = fields.not(filled_fields);    // we will mark only first empty field as invalid    if (filled_fields.length < numberRequired && empty_fields[0] == element) {        return false;    }    return true;}, jQuery.format("Please fill out at least {0} of these fields and one of this associated option."));

Validate:

$("#phoneForm").validate({    rules: {        mobilePhone: {            phone: true,            require_from_group: [1,".mp_phone"],            require_from_group_with_radio: [1,".mp_phone"]        },        personalPhone: {            phone: true,            require_from_group: [1,".mp_phone"],            require_from_group_with_radio: [1,".mp_phone"]        },        workPhone: {            phone: true,            require_from_group: [1,".mp_phone"],            require_from_group_with_radio: [1,".mp_phone"]        }    }   });

Just adding jQuery(this).closest("tr").find("input:radio").is(":checked") in filter condition.

We have just parameterize the radio selector to be generic.