'How to use "invalid-feedback" class with selectpicker from Bootstrap-Select?

I'm using Bootstrap to do some form validation on my web app. With a normal select menu, it would be really easy to have an error message pop-up when the field is invalid:

<select class="someClass" required>
    <option value="">Select an option</option>
    <option>foo</option>
    <option>bar</option>
</select>
<div class="invalid-feedback">Please make a selection.</div>

However, I'm using Bootstrap-Select's "selectpicker" class, and the "invalid-feedback" message in the div no longer works. Is there anyway to force Bootstrap-Select to recognize the "invalid-feedback" class or am I going to have to go about this a different way?



Solution 1:[1]

I figured out how to do this, and more generally this is an answer for anytime you have to "manually" force an error to work with Bootstrap's native validation system. It's really hacky, but I couldn't find anything else that works.

Say you have a "selectpicker" that looks like this:

<select id="mySelect" class="selectpicker" required>
    <option value="">Select an option</option>
    <option>foo</option>
    <option>bar</option>
</select>
<div id="error" class="invalid-feedback">Please make a selection.</div>

The error message "Please make a selection" will not show, even if the select element is invalid; it will show, however, if it also has the "d-block" class:

<div id="error" class="invalid-feedback d-block">Please make a selection.</div>

So to manually force errors, you have to use JavaScript to check for the ":invalid" CSS pseudo-class; if it has this pseudo-class, then you add the "d-block" class to your div to show the error. You can use the matches() method and classList.add():

var selector = document.getElementById("mySelect");
var errorMsg = document.getElementById("error");

if(selector.matches(":invalid"))
{
   errorMsg.classList.add("d-block");
}

You do this to add the message and you can remove it by checking for ":valid" and removing "d-block" from the classList.

Solution 2:[2]

I had multiple versions of the bootstrap-select elements in one of my forms and was having a really hard time getting this to work. The method below won't show the checkmark or x on the input, but it will show the invalid-feedback and valid-feedback boxes properly.

Using the advice from secretagentmango's answer, you can create a function that loops through all of your inputs with the "selectpicker" class, grab their parent form-group element, and then find the children "valid-feedback" and "invalid-feedback" elements to add or remove the d-block class and hide/show them.

function bsSelectValidation() {
  if ($("#myForm").hasClass('was-validated')) {
    $(".selectpicker").each(function (i, el) {
      if ($(el).is(":invalid")) {
        $(el).closest(".form-group").find(".valid-feedback").removeClass("d-block");
        $(el).closest(".form-group").find(".invalid-feedback").addClass("d-block");
      }
      else {
        $(el).closest(".form-group").find(".invalid-feedback").removeClass("d-block");
        $(el).closest(".form-group").find(".valid-feedback").addClass("d-block");
      }
    });
  }
}

Now you need to run this function after form submit, and you can add it directly to the sample code from the Bootstrap Docs:

(function () {
  'use strict';
  window.addEventListener('load', function () {
    // Fetch all the forms we want to apply custom Bootstrap validation styles to
    var forms = document.getElementsByClassName('needs-validation');
    // Loop over them and prevent submission
    var validation = Array.prototype.filter.call(forms, function (form) {
      form.addEventListener('submit', function (event) {
        if (form.checkValidity() === false) {
          event.preventDefault();
          event.stopPropagation();
        }
        form.classList.add('was-validated');
        bsSelectValidation();
      }, false);
    });
  }, false);
})();

The only thing different in the above code from bootstrap's sample is the call to our new function, "bsSelectValidation".

Now you need to listen for changes in the form to automatically update the d-block classes and fix the valid/invalid messages as people make changes to the form:

$('#myForm').change(bsSelectValidation);

Now your select menus should properly show the valid-feedback and invalid-feedback divs on form submit or change.

Solution 3:[3]

I found that if I simply remove the value="" part of the "option" element, then the validation message shows properly. That is, if I don't select anything from the dropdown, the my "invalid-feedback" message shows up. When I select something, it goes away and I can proceed further. It's worth a try if you haven't tried it. My first "option" is simply this: <option>(select)</option> -- no 'value' clause is present. Hope this helps.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 secretagentmango
Solution 2
Solution 3 McAuley