Styling jQuery Validation with Select2 4.0 and Bootstrap 3+

Jay Rizzi picture Jay Rizzi · Jun 11, 2015 · Viewed 15.5k times · Source

I have a project that uses Bootstrap 3.3.4, Select2 4.0, and Jquery Validation 1.13.1

I have set the jquery validator defaults to style bootstrap 3 classes like so

 $.validator.setDefaults({
    errorElement: "span",
    errorClass: "help-block",

    highlight: function (element, errorClass, validClass) {
    $(element).addClass(errorClass);
        $(element).closest('.form-group').removeClass('has-success').addClass('has-error');
    },
    unhighlight: function (element, errorClass, validClass) {
    $(element).removeClass(errorClass);
        $(element).closest('.form-group').removeClass('has-error').addClass('has-success');
    },

    errorPlacement: function(error, element) {
        if(element.parent('.input-group').length) {
           error.insertAfter(element.parent());
        } else {
            error.insertAfter(element);
        }

    }
});

But these defaults do not style select2 fields the same... in the image below, the "metals" select is a bootstrap field, while the "colors" select is a select2 field.

enter image description here

I tried searching other SO's , but all of these use the 3.5.xx version of select2

I included a jsfiddle of the example pictured, I am looking for adjustments to the validator defaults to have select2 look uniform

http://jsfiddle.net/z49mb6wr/

Answer

Sparky picture Sparky · Jun 11, 2015

I tried searching other SO's, but all of these use the 3.5.xx version of select2

There is no secret formula for various versions; you just have to figure it out for your situation. That means you need to inspect the rendered DOM so you know which elements to target and how to target them.

I don't claim that the code below will work for you; it's just an example how to attack this situation.

  1. Write CSS that targets the rendered Select2 element. So whenever the parent container has the class has-error, the Select2 element will be styled as such.

    .has-error .select2-selection {
        border: 1px solid #a94442;
        border-radius: 4px;
    }
    
  2. To get the error message to display after the Select2 element simply requires another conditional within the errorPlacement option along with some jQuery DOM traversal.

    errorPlacement: function (error, element) {
        if (element.parent('.input-group').length) { 
            error.insertAfter(element.parent());      // radio/checkbox?
        } else if (element.hasClass('select2')) {     
            error.insertAfter(element.next('span'));  // select2
        } else {                                      
            error.insertAfter(element);               // default
        }
    }
    
  3. And finally, since interacting with the Select2 does not have any events that the jQuery Validate plugin automatically captures, you will have to write a custom event handler and programmatically trigger validation.

    $('.select2').on('change', function() {
        $(this).valid();
    });
    

Working DEMO: http://jsfiddle.net/z49mb6wr/1/