Friday, March 14, 2014

Bootstrap 3 Form Validation with Glyphicons

Twitter's Bootstrap 3 provides form validation states that allow for styling error, warning and success states.  To use these states, add a .has-error, .has-warning, or .has-success class to the parent element.  Any element with a .control-label, .form-control, or .help-block class will receive the validation style.  The  validation styles are red for errors, tan for warnings, and green for successes.

Bootstrap 3 also allows icons to be added to form elements that contain a .form-control class.  This is accomplished by adding adding an  element with these three classes:  glyphicon, glyphicon-name, and form-control-feedback.   Name is the name of the glyphicon, for example, ok, warning-sign, or remove.


Examples of forms with validation states and icons




Getting Bootstrap to highlight a form field or add an icon was fairly straightforward.  Dynamically adding and changing the icons turned out to be more difficult.  After scouring the web for days, I found only partial solutions.  With the examples I found and some code modification, I was finally able to get this to work.

Requirements:

The tricky part was getting the icon associated with each form element to dynamically change based on validation state.  The jQuery form validation plugin lacked a DOM traversal class that would have made this easy.  The solution was to add an id to the element used for the icon.  That id was named the same as the id from its associated form element, with the addition of "1" on the end.  This allows you to change the icons for any validated form element by simply adding an id attribute to its associated element.

I hope you find this useful.

XHTML
<form class="form-horizontal">
    <div class="form-group has-feedback">
        <label for="fname" class="control-label col-md-6">First Name:</label>
        <div class="col-md-6">
            <input type="text" name="fname" id="fname" class="form-control" placeholder="Enter first name" />
            <span class="glyphicon form-control-feedback" id="fname1"></span>
       </div>
    </div>
    <div class="form-group has-feedback">
        <label for="lname" class="control-label col-md-6">Last Name</label>
        <div class="col-md-6">
            <input type="text" name="lname" id="lname" class="form-control" placeholder="Enter last name" />
            <span class="glyphicon form-control-feedback" id="lname1"></span>
        </div>
    </div>  
    <button type="submit" class="btn btn-primary">Submit</button>
</form>
Javascript
 
$('form').validate({    
    rules: {
        fname: {
            minlength: 3,
            maxlength: 15,
            required: true
        },
        lname: {
            minlength: 3,
            maxlength: 15,
            required: true
        }
    },
    highlight: function(element) {
        var id_attr = "#" + $( element ).attr("id") + "1";
        $(element).closest('.form-group').removeClass('has-success').addClass('has-error');
        $(id_attr).removeClass('glyphicon-ok').addClass('glyphicon-remove');         
    },
    unhighlight: function(element) {
        var id_attr = "#" + $( element ).attr("id") + "1";
        $(element).closest('.form-group').removeClass('has-error').addClass('has-success');
        $(id_attr).removeClass('glyphicon-remove').addClass('glyphicon-ok');         
    },
    errorElement: 'span',
        errorClass: 'help-block',
        errorPlacement: function(error, element) {
            if(element.length) {
                error.insertAfter(element);
            } else {
            error.insertAfter(element);
            }
        } 
 });  
CSS
body {
    padding: 20px;
}

A working example can be found at jsfiddle.net/rtglenn/VwPaR/