FormValidation v0.8.1 is released, supports Bootstrap 4 alpha 3

callback validator

Return the validity from a callback method

Validators

Options

* — Required option

Option HTML attribute Type Description
callback* data-fv-callback-callback Function The callback method
message data-fv-callback-message String The error message. The dynamic message is supported
When setting options via HTML attributes, remember to enable the validator by setting data-fv-callback="true".
The message option can be updated on the fly via the updateMessage() method

The callback method must follow the format below:

function(value, validator, $field) {
    // value is the value of field
    // validator is instance of BootstrapValidator
    // $field is the jQuery object representing the field element

    // Check the field validity
    return true;    // or false
}
The validator is ignored if the callback method returns null

If you want to return a dynamic message, the callback function must return an object containing the valid and message members:

function(value, validator, $field) {
    // ... Do your logic checking
    if (...) {
        return {
            valid: true,    // or false
            message: 'The error message'
        }
    }

    return {
        valid: false,       // or true
        message: 'Other error message'
    }
}

Look at the dynamic message example.

If the validation process takes time, it's recommended to use the tips introduced in the Getting notified while field is being validated example to improve the user experience of the application
Look at this example if you want to attach more data to the returned value and reuse them later

Example

Basic example

In the following form, user is asked to enter a correct answer of simple operation which is generated randomly.

The captcha is also generated after form submission by triggering the err.form.fv event.

<form id="captchaForm" class="form-horizontal">
    <div class="form-group">
        <label class="col-xs-3 control-label" id="captchaOperation"></label>
        <div class="col-xs-5">
            <input type="text" class="form-control" name="captcha" />
        </div>
    </div>

    <div class="form-group">
        <div class="col-xs-5 col-xs-offset-3">
            <button type="submit" class="btn btn-default">Validate</button>
        </div>
    </div>
</form>

<script>
$(document).ready(function() {
    function randomNumber(min, max) {
        return Math.floor(Math.random() * (max - min + 1) + min);
    }

    function generateCaptcha() {
        $('#captchaOperation').html([randomNumber(1, 100), '+', randomNumber(1, 200), '='].join(' '));
    }

    generateCaptcha();

    $('#captchaForm')
        .formValidation({
            framework: 'bootstrap',
            icon: {
                valid: 'glyphicon glyphicon-ok',
                invalid: 'glyphicon glyphicon-remove',
                validating: 'glyphicon glyphicon-refresh'
            },
            fields: {
                captcha: {
                    validators: {
                        callback: {
                            message: 'Wrong answer',
                            callback: function (value, validator, $field) {
                                // Determine the numbers which are generated in captchaOperation
                                var items = $('#captchaOperation').html().split(' '),
                                    sum   = parseInt(items[0]) + parseInt(items[2]);
                                return value == sum;
                            }
                        }
                    }
                }
            }
        })
        .on('err.form.fv', function(e) {
            generateCaptcha();
        });
});
</script>
<form id="callbackForm" class="form-horizontal"
    data-fv-framework="bootstrap"
    data-fv-icon-valid="glyphicon glyphicon-ok"
    data-fv-icon-invalid="glyphicon glyphicon-remove"
    data-fv-icon-validating="glyphicon glyphicon-refresh">

    <div class="form-group">
        <label class="col-xs-3 control-label" id="captchaOperation"></label>
        <div class="col-xs-5">
            <input type="text" class="form-control" name="captcha"
                data-fv-callback="true"
                data-fv-callback-message="Wrong answer"
                data-fv-callback-callback="checkCaptcha" />
        </div>
    </div>
</form>

<script>
// IMPORTANT NOTICE: You have to declare the callback as a global function
// outside of $(document).ready()
function checkCaptcha(value, validator) {
    // Determine the numbers which are generated in captchaOperation
    var items = $('#captchaOperation').html().split(' '),
            sum   = parseInt(items[0]) + parseInt(items[2]);
    return value == sum;
};

$(document).ready(function() {
    // Return a random number between min and max
    function randomNumber(min, max) {
        return Math.floor(Math.random() * (max - min + 1) + min);
    }

    // Generate a sum of two random numbers
    function generateCaptcha() {
        $('#captchaOperation').html([randomNumber(1, 100), '+', randomNumber(1, 200), '='].join(' '));
    }

    generateCaptcha();

    $('#callbackForm').formValidation();
});
</script>

Dynamic message example

The form below ask to enter a secure password, which must satisfies all the following conditions:

  • Must be more than 8 characters long
  • Must contain at least one upper case character
  • Must contain at least one lower case character
  • Must contain at least one digit
<form id="securePasswordForm" class="form-horizontal">
    <div class="form-group">
        <label class="col-xs-3 control-label">Password</label>
        <div class="col-xs-5">
            <input type="password" class="form-control" name="pwd" />
        </div>
    </div>
</form>

<script>
$(document).ready(function() {
    $('#securePasswordForm').formValidation({
        framework: 'bootstrap',
        icon: {
            valid: 'glyphicon glyphicon-ok',
            invalid: 'glyphicon glyphicon-remove',
            validating: 'glyphicon glyphicon-refresh'
        },
        fields: {
            pwd: {
                validators: {
                    notEmpty: {
                        message: 'The password is required and cannot be empty'
                    },
                    callback: {
                        message: 'The password is not valid',
                        callback: function(value, validator, $field) {
                            if (value === '') {
                                return true;
                            }

                            // Check the password strength
                            if (value.length < 8) {
                                return {
                                    valid: false,
                                    message: 'It must be more than 8 characters long'
                                };
                            }

                            // The password doesn't contain any uppercase character
                            if (value === value.toLowerCase()) {
                                return {
                                    valid: false,
                                    message: 'It must contain at least one upper case character'
                                }
                            }

                            // The password doesn't contain any uppercase character
                            if (value === value.toUpperCase()) {
                                return {
                                    valid: false,
                                    message: 'It must contain at least one lower case character'
                                }
                            }

                            // The password doesn't contain any digit
                            if (value.search(/[0-9]/) < 0) {
                                return {
                                    valid: false,
                                    message: 'It must contain at least one digit'
                                }
                            }

                            return true;
                        }
                    }
                }
            }
        }
    });
});
</script>

Showing all messages

It's also possible to show all the messages initially. Then whenever the password passes a particular rule, the message associated with the rule will disappear.

Again, we need to trigger events to archive this. This time, the field events (err.field.fv and success.field.fv) are used.

<form id="passwordForm" class="form-horizontal">
    <div class="form-group" style="margin-bottom: 0;">
        <label class="col-xs-3 control-label">Password</label>
        <div class="col-xs-5">
            <input type="password" class="form-control" name="pwd" />
        </div>
    </div>

    <div class="form-group has-feedback has-error">
        <div class="col-xs-9 col-xs-offset-3">
            <!-- The message container -->
            <div id="messageContainer"></div>
        </div>
    </div>
</form>

<script>
$(document).ready(function() {
    // The rules that a secure password need to follow
    var PASSWORD_RULES = [
        {
            name: 'length',
            message: 'It must be more than 8 characters long',
            check: function(value) {
                return value.length >= 8;
            }
        },
        {
            name: 'upperCase',
            message: 'It must contain at least one upper case character',
            check: function(value) {
                return value !== value.toLowerCase();
            }
        },
        {
            name: 'lowerCase',
            message: 'It must contain at least one lower case character',
            check: function(value) {
                return value !== value.toUpperCase();
            }
        },
        {
            name: 'digit',
            message: 'It must contain at least one digit',
            check: function(value) {
                return value.search(/[0-9]/) >= 0;
            }
        }
    ];

    // Populate the message to given container
    // The container will contain the message for each rule as following
    //  <div id="messageContainer">
    //      <small data-rule="rule name">... message ...</small>
    //  </div>
    for (var i = 0; i < PASSWORD_RULES.length; i++) {
        $('<small/>')
            .addClass('help-block')
            .attr('data-rule', PASSWORD_RULES[i].name)
            .html(PASSWORD_RULES[i].message)
            .appendTo('#messageContainer');
    }

    $('#passwordForm')
        .formValidation({
            framework: 'bootstrap',
            icon: {
                valid: 'glyphicon glyphicon-ok',
                invalid: 'glyphicon glyphicon-remove',
                validating: 'glyphicon glyphicon-refresh'
            },
            fields: {
                pwd: {
                    validators: {
                        notEmpty: {
                            message: 'It is required and cannot be empty'
                        },
                        callback: {
                            callback: function(value, validator, $field) {
                                if (value === '') {
                                    return true;
                                }

                                var passedRules = [];

                                // Loop over the rules
                                for (var i = 0; i < PASSWORD_RULES.length; i++) {
                                    if (PASSWORD_RULES[i].check(value)) {
                                        passedRules.push(PASSWORD_RULES[i].name);
                                    }
                                }

                                if (passedRules.length < PASSWORD_RULES.length) {
                                    return {
                                        valid: false,
                                        passedRules: passedRules
                                    }
                                }

                                return true;
                            }
                        }
                    }
                }
            }
        })
        .on('err.field.fv', function(e, data) {
            // Check if the password field doesn't pass the callback validator
            if (data.field === 'pwd' && data.validator === 'callback') {
                // Get the validator result
                // result consists of valid, passedRules properties
                var result = data.result;

                // Hide the default message
                data.element
                    .closest('.form-group')
                        .find('small[data-fv-for="pwd"][data-fv-validator="callback"]')
                        .hide();

                var $messages = $('#messageContainer').find('small[data-rule]');
                for (var i = 0; i < PASSWORD_RULES.length; i++) {
                    var $message = $messages.filter('[data-rule="' + PASSWORD_RULES[i].name + '"]');

                    $.inArray(PASSWORD_RULES[i].name, result.passedRules) === -1
                        ? $message.fadeIn()     // Show the message if the field doesn't pass the rule
                        : $message.fadeOut();   // Otherwise, hide it
                }
            }
        })
        .on('success.field.fv', function(e, data) {
            if (data.field === 'pwd') {
                // Hide all messages if the field is valid
                $('#messageContainer').find('small[data-rule]').hide();
            }
        });
});
</script>
Example

Related validators

The following validators might be useful to you: