Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery Validate plugin - How to show different error messages based on various conditions

Ok, I know that the first thought here for everyone is to simply create another validation method and message. But here is the deal. We have a form that has a field that is used as Employer Name and Company Name, dependent on what is selected in a dropdown.

What I need to be able to do is when the dropdown shows that they own the company and they didn't fill out the field then it shows one message. If they don't own the company and it is empty then it shows another message.

How would I accomplish this? This is using the latest version of jQuery and the Validate plugin (http://jqueryvalidation.org/).

UPDATE: I present to you the code that I ended up with after the selected answer below was selected...

http://pastebin.com/iG3Z4BbJ

Thanks and enjoy!

Code In Detail:

/**
 * Reference: http://jqueryvalidation.org/rules
 */
$(document).ready(function() {
    var rules = {
        IncomeSource: 'required',
        NetIncome: {
            required: true,
            usDollar: true,
            minDollars: 1
        },
        //Begin - Fields that don't always show
        JobTitle: {
            //required: true,
            nameInput: true
        },
        Employer: {
            //required: true,
            nameInput: true
        },
        EmployerPhone: {
            //required: true,
            phoneUS: true
        },
        BenefitSource: {
            //required: true,
            nameInput: true
        },
        //SemiMonthlySpecifics: 'required', //Select one when Semi-Monthly or Monthly are selected
        //End - Fields that don't always show
        PayFrequency: 'required',
        LastPayDate: {
            required: true,
            pastDate: true,
            date: true
        },
        NextPayDate: {
            required: true,
            futureDate: true,
            date: true
        },
        DirectDeposit: 'required',
        EmploymentLength: 'required',
        ActiveMilitary: 'required',
        RoutingNumber: {
            required: true,
            digits: true,
            rangelength: [9, 9]
        },
        AccountNumber: {
            required: true,
            digits: true,
            rangelength: [4, 17]
        },
        AccountType: 'required'
    };

    //And field specific (and even validation type specific) error messages
    var messages = {
        IncomeSource: ss.i18n._t('IncomeSourceRequiredError'),
        NetIncome: {
            required: ss.i18n._t('NetIncomeRequiredError')
        },
        //Begin - Fields that don't always show
        JobTitle: {
            required: ss.i18n._t('JobTitleRequiredError')
        },
        Employer: {
            required: ss.i18n._t('EmployerRequiredError')
        },
        EmployerPhone: {
            required: ss.i18n._t('EmployerPhoneRequiredError')
        },
        BenefitSource: {
            required: ss.i18n._t('BenefitSourceRequiredError')
        },
        SemiMonthlySpecifics: ss.i18n._t('SemiMonthlySpecificsRequiredError'), //Select one when Semi-Monthly or Monthly are selected
        //End - Fields that don't always show
        PayFrequency: ss.i18n._t('PayFrequencyRequiredError'),
        LastPayDate: {
            required: ss.i18n._t('LastPayDateRequiredError')
        },
        NextPayDate: {
            required: ss.i18n._t('NextPayDateRequiredError')
        },
        DirectDeposit: ss.i18n._t('DirectDepositRequiredError'),
        EmploymentLength: ss.i18n._t('EmploymentLengthRequiredError'),
        ActiveMilitary: ss.i18n._t('ActiveMilitaryRequiredError'),
        RoutingNumber: {
            required: ss.i18n._t('RoutingNumberRequiredError')
        },
        AccountNumber: {
            required: ss.i18n._t('AccountNumberRequiredError')
        },
        AccountType: ss.i18n._t('AccountTypeRequiredError')
    };

    $('#applicationForm').validate({
        //debug: true,
        rules: rules,
        messages: messages,
        errorElement: 'span',
        ignore: '.ignore',
        onfocusout: function( element, event ) {
            $(element).valid();
        },
        invalidHandler: function(event, validator) {
            kclHelpers.openErrorModal(event, validator);
        },
        errorPlacement: function(error, element) {
            var insertLocation = kclHelpers.getInsertLocation(element);
            error.appendTo( insertLocation );
        },
        success: function(label, element) {
            element = $(element);
            var insertLocation = kclHelpers.getInsertLocation(element);
            insertLocation.hide();
            kclHelpers.parentShowSuccess(element, '.control-group');
        },
        //Had to use this for show/hide of errors because error placement doesn't get called on every error.
        showErrors: function(errorMap, errorList) {
            if (this.numberOfInvalids() > 0) {
                //We want to make sure that we show/hide things appropriately on error
                $.each(errorList, function(index, item) {
                    var domElement = item['element'];
                    var message = item['message'];

                    var element = $(domElement);
                    var insertLocation = kclHelpers.getInsertLocation(element);
                    insertLocation.show();
                    kclHelpers.parentShowError(element, '.control-group');
                });
            }

            this.defaultShowErrors();
        }
    });

    $('[rel=tooltip]').tooltip();

    // When the income source is changed, change the form respectively
    $('#IncomeSource').on('change', kclFinancialInfo.incomeSourceChanged);
    $('#PayFrequency').on('change', kclFinancialInfo.payFrequencyChanged);
});



/**
 * This is where we specify functions only for this form
 */
var kclFinancialInfo = function()
{
    return {
        incomeSourceChanged: function() {
            // Store and convert the income source to lowercase
            var val = $(this).val().toLocaleLowerCase();

            // Switch on the income source
            switch (val) {
                // Case for 'benefits'
                case 'benefits':
                    // Do not display the employment section
                    kclFinancialInfo.toggleEmploymentSection(false);

                    // Display the benefit source section
                    kclFinancialInfo.toggleBenefitSource(true);
                    break;

                // Case for 'selfemployment'
                case 'selfemployment':
                    // Display the benefit source section
                    kclFinancialInfo.toggleBenefitSource(false);

                    // Display the employment section
                    kclFinancialInfo.toggleEmploymentSection(true, "Please enter your company's name");

                    // Call to update the labels for the employment section based on income source of 'selfemployment'
                    kclFinancialInfo.updateEmploymentSectionLabels('selfemployment');

                    // Hide the employer phone field
                    kclFinancialInfo.toggleEmployerPhone(true);
                    break;

                // Case for 'job' and default
                case 'job':
                default:
                    // Do not display the benefit source
                    kclFinancialInfo.toggleBenefitSource(false);

                    // Display the employment section
                    kclFinancialInfo.toggleEmploymentSection(true, "Please enter your employer's name");

                    // Call to update the labels for the employment section based on income source of 'job'
                    kclFinancialInfo.updateEmploymentSectionLabels('job');

                    // Do not hide the employer phone field
                    kclFinancialInfo.toggleEmployerPhone(false);
                    break;
            }
        },

        payFrequencyChanged: function() {
            var val = $(this).val().toLocaleLowerCase();

            switch (val) {
                case 'semi_monthly':
                    // Display the Specific SemiMonthly section
                    kclFinancialInfo.toggleSpecificSemiMonthly(true, val);

                case 'monthly':
                    // Display the Specific SemiMonthly section BUT change the labels
                    kclFinancialInfo.toggleSpecificSemiMonthly(true, val);

                    break;
                default:
                    // Do not display the Specific SemiMonthly section
                    kclFinancialInfo.toggleSpecificSemiMonthly(false);
                    break;
            }
        },

        toggleSpecificSemiMonthly: function(show, value) {
            if (show) {
                if (value == 'semimonthly') {
                    $('#specifics-label-for-SemiMonthlySpecifics_day').text(ss.i18n._t('FINANCIAL_INFORMATION_PAGE.SEMI_MONTHLY_SPECIFICS_DAY'));
                    $('#specifics-label-for-SemiMonthlySpecifics_date').text(ss.i18n._t('FINANCIAL_INFORMATION_PAGE.SEMI_MONTHLY_SPECIFICS_DATE'));
                }
                else {
                    $('#specifics-label-for-SemiMonthlySpecifics_day').text(ss.i18n._t('FINANCIAL_INFORMATION_PAGE.MONTHLY_SPECIFICS_DAY'));
                    $('#specifics-label-for-SemiMonthlySpecifics_date').text(ss.i18n._t('FINANCIAL_INFORMATION_PAGE.MONTHLY_SPECIFICS_DATE'));
                }

                $('#semi-monthly-specifics').show().removeClass('hidden');
                $('input[name="SemiMonthlySpecifics"]').rules('add', 'required');
            }
            else {
                kclHelpers.hideMessage('SemiMonthlySpecifics');
                $('#semi-monthly-specifics').hide().addClass('hidden');
                $('input[name="SemiMonthlySpecifics"]').rules('remove', 'required');
            }
        },

        toggleEmployerPhone: function(hide) {
            // If you want to hide the employer phone field
            if (hide) {
                // Hide the employer phone
                $('#employer_phone').hide().addClass('hidden');
                $('employer_phone').rules('remove', 'required');
            }
            // Else (you don't want to hide the employer phone field)
            else {
                // Display the employer phone field
                $('#employer_phone').show().removeClass('hidden');
                $('employer_phone').rules('add', 'required');
            }
        },

        toggleBenefitSource: function(show) {
            // If you want to show the benefit sources section
            if (show) {
                // Show the benefit source section
                $('#benefit_source').show().removeClass('hidden');

                // Since the benefit source section is now visible, make it required
                $('#BenefitSource').rules('add', 'required');

                /**
                 * Hide the WorkPhone validation message if its displayed (it remains on the screen if the user
                 * selects benefits)
                 */
                kclHelpers.hideMessage('WorkPhone');
            }
            // Else (you don't want to show the benefit source section, display the default employment section)
            else {
                // Hide the benefit source section
                $('#benefit_source').hide().addClass('hidden');

                // Since the benefit source is now hidden, it is no longer required
                $('#BenefitSource').rules('remove', 'required');
            }
        },

        toggleEmploymentSection: function(show, employerMessage = '') {
            // If you want to show the employment section
            if (show) {
                // Show the employment section
                $('#employment_section').show();
                $('#JobTitle').rules('add', 'required');
                $('#Employer').rules('add', {
                    required: true,
                    messages: {
                        required: employerMessage
                    }
                });
                $('#EmployerPhone').rules('add', 'required');
            }
            // Else (you don't want to show the employment section)
            else {
                // Hide the employment section
                $('#employment_section').hide();
                $('#JobTitle').rules('remove', 'required');
                $('#Employer').rules('remove', 'required');
                $('#EmployerPhone').rules('remove', 'required');
            }
        },

        updateEmploymentSectionLabels: function(source) {
            // Switch on the income source (now lowercase)
            switch (source.toLocaleLowerCase()) {
                // Case for 'job'
                case 'job':
                    /**
                     * Make sure the job title and employer labels are correct (this is needed in case the labels
                     * need to be changed back to default
                     */
                    $('#JobTitle_label').text(ss.i18n._t('FINANCIAL_INFORMATION_PAGE.JOB_TITLE'));
                    $('#Employer_label').text(ss.i18n._t('FINANCIAL_INFORMATION_PAGE.EMPLOYER'));
                    $('#Employer').attr('placeholder', 'Enter Employer Name');

                    break;
                // Case for 'selfemployment'
                case 'selfemployment':
                    // Change the employer label to correspond to self employment (Employer -> Your Company Name)
                    $('#Employer_label').text(ss.i18n._t('FINANCIAL_INFORMATION_PAGE.SELF_EMPLOYER'));
                    $('#Employer').attr('placeholder', 'Enter Company Name');
                    break;
            }
        }
    }
}();


var kclHelpers = function()
{
    var firstErrorID = '';
    var errorCount = 0;

    return {
        //Expects jQuery element
        getInsertLocation: function(element) {
            var fieldName = element.attr('name');

            if (fieldName == 'Reference_1[Relationship]') {
                fieldName = 'Reference_1-Relationship';
            }
            else if (fieldName == 'Reference_2[Relationship]') {
                fieldName = 'Reference_2-Relationship';
            }

            var insertTo = "#" + fieldName + "-error";
            return $(insertTo);
        },

        //Expects jQuery element and a selector string
        parentShowError: function(element, parentSelector) {
            var parentElem = element.parents(parentSelector);

            if (!parentElem.hasClass('has-error')) {
                parentElem.addClass('has-error');
            }

            parentElem.removeClass('has-success');
        },

        //Expects jQuery element and a selector string
        parentShowSuccess: function(element, parentSelector) {
            var parentElem = element.parents(parentSelector);

            if (!parentElem.hasClass('has-success')) {
                parentElem.addClass('has-success');
            }

            parentElem.removeClass('has-error');
        },

        hideMessage: function(fieldName) {
            if (fieldName == 'CreatePassword') {
                // Clear the Create-Password error message as well as the Confirm-Password error message
                $('#ConfirmPassword-error').hide();
            }

            if (fieldName == 'CellPhone') {
                // Clear the Cell-Phone error message as well as the Home-Phone error message
                $('#HomePhone-error').hide();
            }

            /**
             * Find the id in the form styling file corresponding to field we wish to "clear"
             * And set its "display" value to "none", effectively deleting it
             * This is for the desktop version
             */
            $("#" + fieldName + "-error").hide();
        },

        openErrorModal: function(event, validator) {
            var errorCnt = validator.numberOfInvalids();
            var errors = '';
            var hasSetErrorID = false;
            kclHelpers.errorCount = errorCnt;

            if (errorCnt) {
                var message = "";

                for (var i in validator.errorMap) {
                    if (!hasSetErrorID) {
                        hasSetErrorID = true;
                        kclHelpers.firstErrorID = i;
                    }

                    var str = i;
                    var label = '';

                    if (i == 'AgreeTerms') {
                        label = 'Website terms';
                    }
                    else if (i == 'ContactTerms') {
                        label = 'Contact terms';
                    }
                    else if (i == 'HomePhone') {
                        label = 'Home Phone';
                    }
                    else if (i == 'RoutingNumber') {
                        label = 'Routing Number';
                    }
                    else if (i == 'AccountNumber') {
                        label = 'Account Number';
                    }
                    else if (i == 'SemiMonthlySpecifics') {
                        label = 'Pay Frequency Specifics';
                    }
                    else if (/Reference_1/i.test(str)) {
                        label = 'Reference 1 ' + $("label[for='" + i + "']").text();
                    }
                    else if (/Reference_2/i.test(str)) {
                        label = 'Reference 2 ' + $("label[for='" + i + "']").text();
                    }
                    else {
                        label = $("label[for='" + i + "']").text();
                    }

                    errors += '<li>' + label + ': ' + validator.errorMap[i] + '</li>';
                }

                message += '<ol>' + errors + '</ol>';

                $('#form-error-modal .modal-body .error-count').text(errorCnt);
                $('#form-error-modal ul.error-list').html(message);
                $('#form-error-modal').modal('show');
            }
        }
    }
}();
like image 897
Patrick Avatar asked Jan 05 '14 00:01

Patrick


People also ask

How can I show error message below the textbox in jQuery validation?

Java script ready(function() { $("#basic-form"). validate(); }); This is based on the assumption that you have already added the required JavaScript files. Adding those lines of JavaScript will make sure that your form is properly validated and shows all the error messages.

What is validator addMethod in jQuery?

addMethod( name, method [, message ] ) Description: Add a custom validation method. It must consist of a name (must be a legal javascript identifier), a javascript based function and a default string message.

What is valid () in jQuery?

valid()Returns: Boolean Description: Checks whether the selected form is valid or whether all selected elements are valid.


2 Answers

Here's a much cleaner (and probably the correct) way

messages: {
  RoutingNumber: {
    required:"Message1",
    digits: "Message2",
    rangelength: "Message 3"
  }
}

For more validation methods: List of built in validation methods

like image 139
stuartdotnet Avatar answered Nov 03 '22 00:11

stuartdotnet


Use the .rules('add') method to dynamically change the message on change of the select. Then use the .valid() method to trigger a new test on the field in order to instantly update the message.

$(document).ready(function () {

    $('#myform').validate({
        rules: {
            type: {
                required: true
            },
            theName: {
                required: true
            }
        }
    });

    $('select[name="type"]').on('change', function () {
        var theMessage,
            theType = $(this).val();
        if (theType == 'employer') {
            theMessage = "Required Message 1";
        } else if (theType == 'company') {
            theMessage = "Required Message 2";
        } else {
            theMessage = "This field is required.";
        }
        // dynamically change the message
        $('input[name="theName"]').rules('add', {
            messages: {
                required: theMessage
            }
        });
        // trigger immediate validation to update message
        $('input[name="theName"]').valid();        
    });

});

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

like image 32
Sparky Avatar answered Nov 03 '22 01:11

Sparky