user558085 user558085 - 6 months ago 21
jQuery Question

jQuery require_from_group if a form field is filled/selected

I have a page which allows people to input details of up to five Referrals which are non-compulsory. Each group of referral is contained within its own

div
.

When any one of the fields is filled/selected, I need to check that all the other fields and at least one contact number within the same
div
are filled as well. If no field is filled/selected, the form should pass through successfully.

I am stuck at this for the longest as I only managed to use
require_from_group
for the contact numbers which checks for at least one contact number filled, but it doesn't fulfill what I require.

HTML code for form fields

<div id="Referral1" class="parentClass">

<div class="form-group row">
<div class="control-label col-md-12" style="color: #6d0017;"><strong>My Referral: </strong></div>
</div>

<div class="form-group row">
<div class="control-label col-md-4 required">Salutation</div>
<div class="col-md-5">
<select type="text" class="form-control" name="Referral_1_Salutation">
<option value="" selected disabled>Please select</option>
<option value="Mr">Mr</option>
<option value="Mrs">Mrs</option>
<option value="Ms">Ms</option>
<option value="Mdm">Mdm</option>
</select>
</div>
<div class="col-md-3">
<p class="error-msg"></p>
</div>
</div>

<div class="form-group row">
<div class="control-label col-md-4 required">Name</div>
<div class="col-md-5">
<input type="text" class="form-control" name="Referral_1_Name" value="" maxlength="50">
</div>
<div class="col-md-3">
<p class="error-msg"></p>
</div>
</div>

<div class="form-group row">
<div class="control-label col-md-4 required-atleastone" style="padding-right:0;">Contact Number (Mobile)</div>
<div class="col-md-5">
<input type="text" class="oneormore form-control" name="Referral_1_Contact_Number_Mobile" value="" maxlength="20">
</div>
<div class="col-md-3">
<p class="error-msg"></p>
</div>
</div>

<div class="form-group row">
<div class="control-label col-md-4 required-atleastone" style="padding-right:0;">Contact Number (Home)</div>
<div class="col-md-5">
<input type="text" class="oneormore form-control" name="Referral_1_Contact_Number_Home" value="" maxlength="20">
</div>
<div class="col-md-3">
<p class="error-msg"></p>
</div>
</div>

<div class="form-group row">
<div class="control-label col-md-4 required-atleastone" style="padding-right:0;">Contact Number (Office)</div>
<div class="col-md-5">
<input type="text" class="oneormore form-control" name="Referral_1_Contact_Number_Office" value="" maxlength="20">
</div>
<div class="col-md-3">
<p class="error-msg"></p>
</div>
</div>

<div class="form-group row">
<div class="control-label col-md-4 required">Email Address</div>
<div class="col-md-5">
<input type="text" class="form-control" name="Referral_1_Email" value="" maxlength="50">
</div>
<div class="col-md-3">
<p class="error-msg"></p>
</div>
</div>

<div class="form-group row">
<div class="control-label col-md-4 required">Best Time to Call
<span class="popovers" data-toggle="popover" data-content="Our office hours are from 8.45 am to 6.00 pm, Monday to Friday (except public holidays). If you send this after office hours, we will respond to you the next working day."><i class="fa fa-info-circle text-red"></i></span>
</div>
<div class="col-md-5">
<select type="text" class="form-control" name="Referral_1_Best_Time_To_Call">
<option value="" selected disabled>Please select</option>
<option value="9am_to_12pm">9am - 12 pm</option>
<option value="12pm_to_2pm">12pm - 2pm</option>
<option value="2pm_to_4pm">2pm - 4pm</option>
<option value="4pm_to_6pm">4pm - 6pm</option>
<option value="Anytime">Anytime</option>
</select>
</div>
<div class="col-md-3">
<p class="error-msg"></p>
</div>
</div>
</div>


jQuery function which currently checks that at least one contact number is needed to be filled

var initCustomerReferralFormComponents = function() {
jQuery.validator.addMethod("require_from_group_contact", 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 upload

jQuery(selector, element.form).off('.require_from_group_contact');

if (this.settings.onkeyup) {
jQuery(selector, element.form).on({
'keyup.require_from_group_contact': function (e) {
jQuery(selector, element.form).valid();
}
});
}
if (this.settings.onfocusin) {
jQuery(selector, element.form).on({
'focusin.require_from_group_contact': function (e) {
jQuery(selector, element.form).valid();
}
});
}
if (this.settings.click) {
jQuery(selector, element.form).on({
'click.require_from_group_contact': function (e) {
jQuery(selector, element.form).valid();
}
});
}
if (this.settings.onkeyup) {
jQuery(selector, element.form).on({
'keyup.require_from_group_contact': function (e) {
jQuery(selector, element.form).valid();
}
});
}
return validOrNot;
}, "Fill in all fields.");

$("#customer_referral").validate({
rules: {
Referral_1_Contact_Number_Mobile: {
require_from_group_contact: [1, ".oneormore"]
},
Referral_1_Contact_Number_Home: {
require_from_group_contact: [1, ".oneormore"]
},
Referral_1_Contact_Number_Office: {
require_from_group_contact: [1, ".oneormore"]
}
},
highlight: function(element, errorClass) {
$(element).closest('.form-group').removeClass('has-success').addClass('has-error');
},
errorPlacement: function (error, element) {
$(element).closest('.form-group').find('.error-msg').text(error.text());
},
unhighlight: function(element) {
$(element).closest('.form-group').removeClass('has-error').addClass('has-success')
},
submitHandler: function(form) {
console.log('form submit');
form.submit();
}
});
}

Answer

It's very tedious...

You create a conditional function to see if any of the other four fields are filled out and then apply the parameters of the require_from_group rule using a function.

Do the same for the other fields but instead using the required rule.

Adjust accordingly.

rules: { 
    Referral_1_Contact_Number_Mobile: {
        require_from_group: function(element) {
            if ($('[name="Referral_1_Salutation"]').is(':filled') || $('[name="Referral_1_Name"]').is(':filled') || $('[name="Referral_1_Email"]').is(':filled') || $('[name="Referral_1_Best_Time_To_Call"]').is(':filled')) {
                return [1, ".oneormore"];
            } else {
                return [0, ".oneormore"];
            }
        }
    },
    ....
    // repeat same for remaining contact numbers
    ....

    Referral_1_Salutation: {
        required: function(element) {
            return ($('[name="Referral_1_Name"]').is(':filled') || $('[name="Referral_1_Email"]').is(':filled') || $('[name="Referral_1_Best_Time_To_Call"]').is(':filled') || $('[name="Referral_1_Contact_Number_Mobile"]').is(':filled') || $('[name="Referral_1_Contact_Number_Home"]').is(':filled') || $('[name="Referral_1_Contact_Number_Office"]').is(':filled'));
        }
    },
    ....
    // repeat same for remaining other fields
    ....

Working DEMO: http://jsfiddle.net/cd5gy73u/


EDIT:

Much of the code could be replaced with the skip_or_fill_minimum rule:

http://jsfiddle.net/yo2vjwus/