Menu

jQuery form Validation: Demo Version 1.5.3 2 years ago

Here are a few example of how the jQuery Validation can be used to validate forms. These examples were coded to demonstrate the possibilities and results that can be achieved using this JavaScript plugin. It is for you to decide how to skin and customize the functionalities of your form(s).

Basic demos

Signin v1
  • Default initialization
  • The errors are displayed as inline with append insertion
  • Both fields are using NOTEMPTY as data-validation rule
  • Errors are cleared on focusin by default


    $('#form-signin_v1').validate();

        

        

    
Signin v2
  • Using scrollToError so the page is scrolled to the first error, also works for $.addError
  • Add and Remove custom error message using $.addError and $.removeError api
  • Output the errors from PHP inside the Validation instance on page reload!
  • Here is how this example works
    1. Form Validation is initialized
    2. Once the inputs are valid, form is POST and validated by PHP.
    3. The page reloads, errors are echo inside an input[type="hidden"]
    4. JavaScript listens for that input, converts the string into a JSON object
    5. The object gets passed to $(form).addError(errorObject).
    6. * Use the same form selector for $.validate() and $.addError() or it will not work!


    // This instance has priority over global messages
    $('form#form-signin_v2').validate({
        submit: {
            settings: {
                scrollToError: {
                    offset: -100,
                    duration: 500
                }
            }
        }
    });

    // Error object is echo'd by PHP inside this input
    var error = $('#signin_v2-errors').val();

    if (error) {
        try {

            $('form#form-signin_v2').addError(JSON.parse(error));

        } catch (e) {
            // Log error (e)
        }
    }

    $('#add-custom-error-signin_v2').click( function () {
        // Add custom error
        $('form#form-signin_v2').addError({
            'signin_v2[username]': 'Custom error :[',
            'signin_v2[password]': [
                'Oh ..... :(',
                'Yeah... Oh... :/'
            ]
        });
    });

    $('#remove-custom-error-signin_v2').click( function () {
        // Remove custom error
        //$('form#form-signin_v2').removeError([
        //    'signin_v2[username]',
        //    'signin_v2[password]'
        //]);
        $('form#form-signin_v2').removeError()
    });
        

        

    


if (empty($_POST)) {
    exit();
}

$signin_v2_username = $_POST[key($_POST)]['username'];
$signin_v2_password = $_POST[key($_POST)]['password'];

// Code to Validate the inputs goes here

// Return errors for the example
// inputName => {errorString|errorArray}
$signin_v2_errors = htmlspecialchars(json_encode(
    array(
        "signin_v2[username]" => "Your username is bad and you should feel bad!",
        "signin_v2[password]" => array(
            "2 errors on password input",
            "Your password is not safe!"
        )
    )
));        
Signin v3
  • Username is using [L>=6, L<=18, MIXED] rules inside data-validation attribute
  • Errors are cleared on input keypress
  • data-validation-reverse is used to reverse the regex. /^((?!admin).)*$/i could be used without the reversed attribute.
  • Custom submit button instead of using the default input[type='submit']
  • Custom errorClass to apply different styles on input and label
  • Custom errorListClass to apply different styles on the list of errors
  • Using inputContainer means that the input is located inside this block. errorClass will be added using $(input).parentsUntil(node, inputContainer)


    $('#form-signin_v3').validate({
        submit: {
            settings: {
                clear: "keypress",
                button: 'button#submit-signin_v3',
                errorClass: 'custom-error',
                errorListClass: 'custom-error-list',
                inputContainer: '.field'
            }
        }
    });

        

        

    
Contact v1
  • Using a Bootstrap-like form structure and customized error display.
  • Validation on select and textarea.
  • Using NAME validation for full name input.
  • All field errors are being displayed when allErrors is set to true.
  • Defining a new default message for NOTEMPTY on this instance only (used for translated errors), remember using $ in your message will be replaced by the input name if you need the dollar sign to be displayed use the HTML code.
  • Defining window.Validation.labels, $(form).validate({labels:{}}) and data-validation-label to override the default inputName inside the error messages.


    // Custom labels for error display
    Validation.labels = {
        'contact_v1[email]': 'Custom label name from configuration'
    };

    // This instance has priority over global messages
    $('#form-contact_v1').validate({
        submit: {
            settings: {
                inputContainer: ".control-group",
                allErrors: true,
                errorListClass: "attention icon"
            }
        },
        messages: {
            'NOTEMPTY': 'Overriding the NOTEMPTY message for this instance'
        },
        labels: {
            'contact_v1[message]': 'Custom label name from initialization'
        }
    });

        

        

    
Signup v1
  • Using Bootstrap Popover plugin to display helpers on input focus
  • The errorListClass have a class override to allow deeper CSS customisation
  • The confirm password and confirm email have [V==inputName] and has to match the referred input value
  • onBeforeSubmit callback calls myBeforeSubmit function to add a readonly attribute and triggers a loading animation
  • onSubmit does extra manipulation(s) (could be an ajax call) and submits the form afterwards using node.submit()


    // Bootstrap popovers
    $('#form-signup_v1 [data-toggle="popover"]').popover({trigger: 'focus', placement: 'left'});

    $('#form-signup_v1').validate({
        submit: {
            settings: {
                inputContainer: '.field',
                errorListClass: 'ui red pointing below label'
            },
            callback: {
                onBeforeSubmit: function (node) {

                    myBeforeSubmitFunction(':D', ':)', node);

                },
                onSubmit: function (node, formData) {

                    console.log('#' + node.id + ' has a submit override.');
                    console.log(formData);

                    //node[0].submit();

                }
            }
        }
    });

    function myBeforeSubmitFunction(a, b, node) {

        console.log(a, b);

        node.find('input:not([type="submit"]), select, textarea').attr('readonly', 'true');
        node.append('<div class="ui active loader"></div>');

    }

        

        

    
Debug v1
  • This example shows a BAD implementation and how to debug to make it work!
  • Open your Console (F12) and reload the page. You should see an expandable table --- jQuery Form Validation Debug ---, press it.
  • WARNING - display: "blue" - unsupported option, only "inline" or "block" are valid options, etc.
  • Try to submit the form while all fields are left empty, a new table --- jQuery Form Validation Debug --- appears, press it.
  • WARNING - Invalid [data-validation-regex] on input debug_v1[username], the regex is invalid therefore the validation rule is skipped.
  • ERROR - Missing input [name], the validation input MUST have a name to be validated if not it will be skipped.


    // This instance has priority over global messages
    $('form#form-debug_v1').validate({
        submit: {
            settings: {
                allErrors: true,
                scrollToError: {
                    offset: -100,
                    duration: 500,
                    blabla: 123
                },
                display: 'blue'
            },
            hello: {
                test: 'test'
            },
            callback: {
                onInit: "coucou"
            }
        },
        hi: {
            foo: 'bar'
        },
        debug: true
    });
        

        

    

Advanced demos

Signin v4
  • The errors are inserted prepend and displayed block
  • Errors are not cleared on input focusin or keypress
  • Username has data-validation-regex="/^(?![0-9])((?!admin).)*$/i" attribute to prevent the username from starting with a digit or containing "admin".
  • onError submit callback alerts the list of error that occurred.
  • $.alterValidationRules adds COMPLEX rule (you can build your own custom rules). That rule is used on the password input field (see HTML tab).


    // Adds 'COMPLEX' rule for every Validation instances
    $.alterValidationRules({
        rule: 'COMPLEX',
        regex: /^(?=.*\d+)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{6,16}$/,
        message: '$ must contain at least one number, one letter, one capitalized letter and between 6 - 16 characters.'
    });

    $.validate({
        submit: {
            settings: {
                form: '#form-signin_v4',
                clear: false,
                inputContainer: '.field',
                display: 'block',
                insertion: 'prepend',
                scrollToError: true
            },
            callback: {
                onError: function (node, errors) {

                    var text = "The following errors were found: \n";
                    for (var inputName in errors) {
                        for (var i = 0; i < errors[inputName].length; i++) {
                            text += errors[inputName][i] + '\n';
                        }
                    }

                    alert(text);

                }
            }
        },
        rules: {
            'MIXED': /^[a-z0-9]+$/
        },
        messages: {
            'MIXED': 'Altered mixed for this instance only!'
        }
    });

        

        

    
Signup v2
  • Name input has data-validation="[OPTIONAL, L>=2, TRIM]" means that the field can be blank. However if the field is not empty, the other Validation rule(s) will be applied.
  • Using dynamic means that the Validation rules on attributes data-validation and data-validation-regex will be validated on focusout.

  • The DOM is modified using onSuccess and onError callbacks to display the dynamic Validation result.
  • Radio input requires data-validation-group to be applied. This group must be the label#id where the errors will be displayed.
  • Using jQuery Datepicker to select birthday
  • Creating a custom rule DATE_DATEPICKER for the Birthday field using jQuery Datepicker.
  • The "I agree" checkbox has a validation of NOTEMPTY therefore making it required to be checked.
  • Custom CSS have been added on radio and checkbox so the error box is positioned properly.


    // Add jquery-ui ..
    //$("#signup_v2-birthday").datepicker({
    //    changeMonth: true,
    //    changeYear: true
    //});

    $.alterValidationRules({
        rule: 'DATE_DATEPICKER',
        regex: /^\d{2}\/\d{2}\/\d{4}$/,
        message: '$ date must use format MM/DD/YYYY to be valid.'
    });

    $.validate({
        submit: {
            settings: {
                form: '#form-signup_v2',
                inputContainer: '.field',
                errorListClass: 'ui red pointing below label'
            },

            callback: {
                onSubmit: function (node, formData) {

                    console.log('~~~~~~~~~')
                    console.log(node)
                    console.log(formData)
                    console.log('~~~~~~~~~')


                }
            }

        },
        dynamic: {
            settings: {
                trigger: 'focusout'
            },
            callback: {
                onSuccess: function (node, input, keyCode) {
                    if ($(input).val()) {
                        $(input).parent().find('.ui.corner.label').removeClass('red').addClass('green');
                    }
                },
                onError: function (node, input, keyCode, error) {
                    $(input).parent().find('.ui.corner.label').removeClass('green');
                }
            }
        }
    });

        

        

    
Signup v3
  • Both Username and Email have a dynamic Validation. The data-validation and data-validation-regex rules are valid after the delay of keyup an Ajax request will be sent via onSuccess to a validate controller to check for availability.
  • Using dynamic means that the Validation rules on attributes data-validation and data-validation-regex will be validated on input trigger and not only on the form submit.
  • Select Email input, press a key, wait 1 second and watch the field being validated.
  • Possibility to do extra operation(s) depending on the keyCode third callback parameter


    var options = {
        submit: {
            settings: {
                form: '#form-signup_v3',
                clear: 'keypress',
                inputContainer: '.field',
                errorListClass: 'ui red pointing below label'
            }
        },
        dynamic: {
            settings: {
                trigger: 'keyup',
                delay: 1000
            },
            callback: {
                onSuccess: function (node, input, keyCode) {

                    console.log(keyCode + ' was pressed!');

                    var inputName = $(input).attr('name');

                    if ($.inArray(inputName, ['signup_v3[username]', 'signup_v3[email]']) === -1) {
                        return false;
                    }

                    $.ajax({
                        type: 'POST',
                        data: {form: 'signup_v3', input: inputName, value: $(input).val()},
                        url: '/validate/',
                        dataType: 'json',
                        success: function ( response, textStatus, jqxhr ) {

                            if (!response.status) {

                                $(input).parent().find('.ui.corner.label').removeClass('green');

                                $('#form-signup_v3').addError(response.error)

                            } else {

                                $(input).parent().find('.ui.corner.label').addClass('green');

                            }

                        }
                    });

                },
                onError: function (node, input, keyCode, error) {
                    $(input).parent().find('.ui.corner.label').removeClass('green');
                }
            }
        }
    }

    $.validate(options);

    $('#destroy-signup_v3').click( function () {
        $('#form-signup_v3').validate('destroy');
    });

    $('#init-signup_v3').click( function () {
        $.validate(options);
    });

        

        

    


if (empty($_POST) || empty($_POST['input']) || empty($_POST['value'])) {
    exit();
}

$status = false;
$data = null;
$error = null;

switch ($_POST['input']) {

    case 'signup_v3[username]':

        if (strtolower($_POST['value']) === "testuser") {

            $error = array(
                $_POST['input'] => 'Username is Taken.'
            );

        } else {

            $status = true;
            $data = array(
                $_POST['input'] => 'Username is Available!'
            );

        }

        break;

    case 'signup_v3[email]':

        if (strtolower($_POST['value']) === "test@test.test") {

            $error = array(
                $_POST['input'] => 'An account using this email is already registered.'
            );

        } else {

            $status = true;
            $data = array(
                $_POST['input'] => 'Email is Available!'
            );

        }

        break;

}

echo json_encode(
    array(
        'status' => $status,
        'data' => $data,
        'error' => $error
    )
);        
Purchase v1
  • Requires $.creditCardValidator plugin to validate the credit card input
  • Number of items has [NUMERIC, V<0, V<=6] meaning that 6 could also be a variable coming from backend that reflects the inventory quantities

Your order

Payment Method



    // Simple toggle to display the payment methods
    // Note: DISABLED fields will NOT be validated
    $('input[name="purchase_v1[method]"]').on('change', function () {

        $('[data-toggle-method]').addClass('hidden')
            .find('input').attr('disabled', 'disabled');

        $('[data-toggle-method="' + $(this).val() + '"]').removeClass('hidden')
            .find('input').removeAttr('disabled');

    });

    // Bootstrap popovers
    $('#form-purchase_v1 [data-toggle="popover"]').popover({trigger: 'hover', placement: 'right', html: true});

    $.validate({
        submit: {
            settings: {
                form: '#form-purchase_v1',
                clear: 'focusin',
                inputContainer: '.field',
                errorListClass: 'ui red pointing below label'
            }
        },
        dynamic: {
            settings: {
                trigger: 'keypress',
                delay: 1000
            },
            callback: {
                onSuccess: function (node, input, keyCode) {

                    if ($(input).attr('name') !== "purchase_v1[card-number]" && $(input).val()) {
                        $(input).parent().find('.ui.corner.label').removeClass('red').addClass('green');
                    }

                },
                onError: function (node, input, keyCode, errors) {
                    $(input).parent().find('.ui.corner.label').removeClass('green');
                }
            }
        }
    });

    // Validate the credit card with jQuery Credit Card Validator plugin
    $("#purchase_v1-card-number").validateCreditCard(
        function (result) {

            var cards = $('#purchase_v1-card-list li'),
                label = $("#purchase_v1-card-number").siblings('.ui.corner.label');

            if (result.card_type === null) {
                cards.removeClass('off');
                label.removeClass("green");
                return;
            }

            cards.addClass('off');
            cards.siblings('.' + result.card_type.name).removeClass('off');

            return result.length_valid && result.luhn_valid ?
                label.addClass("green") :
                label.removeClass("green");

        },
        { accept: ['visa', 'mastercard', 'discover', 'amex'] }
    );