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

Validating fields that depend on each other

Examples

In fact, a form might need to validate multiple fields which any of them depends to each other. Changing value of any field will effect to the validity of other one.

For instance, a form for creating new event often have two fields for indicating the start and end date of the event. The start date must be earlier than the end one. And vice versa, the end date must be later than the start one. User usually fill in the start date field first, and then the end date one. If the end date is not later than the start one, the form informs that the end date is not valid. It behaves as expected.

For this specific form, we can use the min and max options provided by the date validator:

$('#eventForm').formValidation({
    fields: {
        startDate: {
            validators: {
                date: {
                    message: 'The start date is not valid',
                    format: 'YYYY-MM-DD',
                    max: 'endDate'
                }
            }
        },
        endDate: {
            validators: {
                date: {
                    message: 'The end date is not valid',
                    format: 'YYYY-MM-DD',
                    min: 'startDate'
                }
            }
        }
    }
});

The problem comes out when user try to adjust the start date being earlier than the current end date. Despite the fact that the end date is valid now, it is still marked as invalid.

In order to fix this, when the start date is valid, we need to revalidate the end date if it's not valid. The onSuccess callback, isValidField() and revalidateField() methods are used as in the following code snippet:

$('#eventForm').formValidation({
    fields: {
        startDate: {
            validators: {
                ...
            },
            onSuccess: function(e, data) {
                // data.fv is the plugin instance

                // If the end date isn't valid
                if (!data.fv.isValidField('endDate')) {
                    // Revalidate it
                    data.fv.revalidateField('endDate');
                }
            }
        },
        endDate: {
            validators: {
                ...
            },
            onSuccess: function(e, data) {
                // data.fv is the plugin instance

                // Revalidate the start date if it's not valid
                if (!data.fv.isValidField('startDate')) {
                    data.fv.revalidateField('startDate');
                }
            }
        }
    }
});
You also can trigger the success.field.fv event as seen in the Comparing dates example
It's recommended to use a date picker along with the date input. There are a lot of examples showing how to integrate FormValidation with popular date picker plugins
<form id="eventForm" class="form-horizontal">
    <div class="form-group">
        <label class="col-xs-3 control-label">Event name</label>
        <div class="col-xs-5">
            <input type="text" class="form-control" name="name" />
        </div>
    </div>

    <div class="form-group">
        <label class="col-xs-3 control-label">Location</label>
        <div class="col-xs-5">
            <input type="text" class="form-control" name="location" />
        </div>
    </div>

    <div class="form-group">
        <label class="col-xs-3 control-label">Start date</label>
        <div class="col-xs-4">
            <input type="text" class="form-control" name="startDate" />
        </div>
    </div>

    <div class="form-group">
        <label class="col-xs-3 control-label">End date</label>
        <div class="col-xs-4">
            <input type="text" class="form-control" name="endDate" />
        </div>
    </div>

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

<script>
$(document).ready(function() {
    $('#eventForm').formValidation({
        framework: 'bootstrap',
        icon: {
            valid: 'glyphicon glyphicon-ok',
            invalid: 'glyphicon glyphicon-remove',
            validating: 'glyphicon glyphicon-refresh'
        },
        fields: {
            name: {
                validators: {
                    notEmpty: {
                        message: 'The event name is required'
                    }
                }
            },
            location: {
                validators: {
                    notEmpty: {
                        message: 'The location is required'
                    }
                }
            },
            startDate: {
                validators: {
                    notEmpty: {
                        message: 'The start date is required'
                    },
                    date: {
                        message: 'The start date is not valid',
                        format: 'YYYY-MM-DD',
                        max: 'endDate'
                    }
                },
                onSuccess: function(e, data) {
                    // data.fv is the plugin instance
                    // Revalidate the end date if it's not valid
                    if (!data.fv.isValidField('endDate')) {
                        data.fv.revalidateField('endDate');
                    }
                }
            },
            endDate: {
                validators: {
                    notEmpty: {
                        message: 'The end date is required'
                    },
                    date: {
                        message: 'The end date is not valid',
                        format: 'YYYY-MM-DD',
                        min: 'startDate'
                    }
                },
                onSuccess: function(e, data) {
                    // data.fv is the plugin instance
                    // Revalidate the start date if it's not valid
                    if (!data.fv.isValidField('startDate')) {
                        data.fv.revalidateField('startDate');
                    }
                }
            }
        }
    });
});
</script>