jQuery Custom Validation Rule – fieldPresent

Sam Deering
Share

This post shows you how to add a custom validation rule to your forms using the jQuery.validate.js plugin. This post supports the Setup form validation using jQuery in just 2 minutes post. I used the $.validator.addMethod() function to setup the custom validation rules. I’ve added a Live Demo below.

Update: 30/06/2013: Added custom validation rule for date of birth.

Examples

The example below shows a custom validation rule which checks that both a name and email are present. If the name is present the email must be present and vice versa.

Example on left field validation.
b5f8ddf05cc9e0d77165aab60fe3adec[1]

Example on right field validation.
4f5d3b79c2a2c8284b4b23b785e4f893

Example on both in action on multiple pairs.
fb3c37c4856ac43787f233f40d40a973

Live Demo


Edit in jsfiddle

JQUERY

There is a patched version of this snippet at the end of the post, which fixes some cross browser and validation recursion issues.

$.validator.addMethod("fieldPresent", function (value, element, options)
{
    //we need the validation error to appear on the correct element
    var targetEl = $('input[name="'+options.data+'"]'),
        bothEmpty = (value == targetEl.val() == '');

    //trigger error class on target input
    (bothEmpty) ? targetEl.addClass('error') : targetEl.removeClass('error');
    return !bothEmpty;
},
    "Friend's name and email required."
);

$('#myForm').validate({
    onkeyup: true,
    rules: {
        "friend1-name": { "fieldPresent": { data: "friend1-email" } },
        "friend1-email": { "fieldPresent": { data: "friend1-name" } }             
    },
    submitHandler: function(form) {

        console.log('passed validation.');
        //submit form handler
    }
});

HTML

CSS

.control-group {
    width: 100%;
}

.control-group-inner {
    width: 50%;
    float: left;
    display: inline-block;
}

If the jQuery code snippet above doesn’t work here is a newer version to remove some bugs. Kind of want to avoid setTimeouts as they are bad coding practice…

//custom validation: each friend entered must have an email and a name
$.validator.addMethod("fieldPresent", function (value, element, options)
{
    //we need the validation error to appear on the correct element
    var targetEl = $('input[name="'+options.data+'"]'),
        targetEmpty = (targetEl.val() == ''),
        elEmpty = (value == ''),
        bothEmpty = elEmpty && targetEmpty;

    //trigger error class on target input
    if (!bothEmpty && targetEmpty)
    {
        //error msg doesn't exist yet so wait...
        setTimeout(function()
        {
            if (targetEl.closest('.control-group-inner').find('label.fieldPresentError').length == 0)
            {
                targetEl.addClass('error');
                if (!elEmpty) $(element).closest('.control-group-inner').find('label.fieldPresentError').remove();
                targetEl.closest('.control-group-inner').find('label.fieldPresentError').remove();
                targetEl.after("");
            }
        }, 500);
    }

    return (bothEmpty || !elEmpty);
},
    "Friend's name and email required."
);

Validate Date of Birth (3 inputs)

How to validate dob which contains 3 inputs for day, month & year. You’ll need to add a custom validation rule.

//custom validation for dob
$.validator.addMethod("dobValid", function (value, element, options)
{
    //we need the validation error to appear on the correct element
    var day = $('input[name="dob-day"]'),
        month = $('input[name="dob-month"]'),
        year = $('input[name="dob-year"]'),
        anyEmpty = ( day.val() == '' || month.val() == '' || year.val() == '' );

    if (anyEmpty) {
        day.add(month).add(year).addClass('error');
    }
    else {
        day.add(month).add(year).removeClass('error');
    }

    return !anyEmpty;
},
    "Please enter your date of birth."
);


...


$form.validate({
    rules: {

        ...

        "dob-year": { required: "required", dobValid: true }

        ...

    },
    messages: {

        ...

    },
    submitHandler: function(form) {

        ...
        
    }
});