49

I'm trying to validate select2 field using jquey.validation plugin but nothing happens.

I want to make select required field.

I'm using this custom validation function:

$.validator.addMethod("requiredcountry", function(value, element, arg){
              return arg != value;
         }, "Value must not equal arg.");

and this is the rule:

rules:
{
 country:
 {
         required: true,
         requiredcountry: ""
 }
}

What select2 field should I use for the rule to match?

I appreciate any idea how to make select2 working together with jquery.validation

10x

Jim Geurts
  • 20,189
  • 23
  • 95
  • 116
user2323711
  • 843
  • 1
  • 7
  • 13

15 Answers15

47

Just add ignore: [], in Your form validation function. It will enable hidden field validation.So You will get validation for Select 2

$("#ContactForm").validate({
  ignore: [],       
  rules: {
    //Rules
  },
  messages: {
    //messages
  }
});
Sicco
  • 6,167
  • 5
  • 45
  • 61
ABIRAMAN
  • 929
  • 8
  • 12
  • That is so simple - yet couldn't find any mention in the docs for Select2 – SolaceBeforeDawn Feb 08 '17 at 00:49
  • Fantastic, fixed my problem after a long time trying myself! +1 – e_i_pi Apr 11 '17 at 04:26
  • I just encountered the same issue and in case anyone is wondering why it is occurring and why ignore: [] is fixing it - here is my story: 1. I added "hidden" class to the select which applies display: none to the element 2. This makes Validation to interpret the – yavor.vasilev Apr 17 '19 at 11:43
  • EDIT: I think the issue comes from the "hidden" keyword, not the css styles because when I change the class to something else the issue is no longer reproducible. – yavor.vasilev Apr 18 '19 at 07:52
  • 1
    When i added ignore:[], it is validating but the form does not submit. – user3653474 Mar 28 '20 at 06:31
33

As a tip, please consider that the validate js bind itself to changes of select not select 2. This cause problem in below case:

  1. There is a required select box which is converted to select2
  2. You click the submit and the error shows that the select box is required.
  3. You select some option from select 2.
  4. The validation error does not hide automatically

You can fix it with:

     $("select").on("select2:close", function (e) {  
        $(this).valid(); 
    });
Alireza Fattahi
  • 42,517
  • 14
  • 123
  • 173
23

In Addition to ABIRAMAN's answer here is some code that

  • Makes the select2 box red when errors appear
  • List the error below the select2 box

<style>
  span.error{
    outline: none;
    border: 1px solid #800000;
    box-shadow: 0 0 5px 1px #800000;
  }
</style>

<script>
 $("#form").validate({
     rules: {
       email: "required"
     },
     highlight: function (element, errorClass, validClass) {
       var elem = $(element);
       if (elem.hasClass("select2-hidden-accessible")) {
           $("#select2-" + elem.attr("id") + "-container").parent().addClass(errorClass); 
       } else {
           elem.addClass(errorClass);
       }
     },    
     unhighlight: function (element, errorClass, validClass) {
         var elem = $(element);
         if (elem.hasClass("select2-hidden-accessible")) {
              $("#select2-" + elem.attr("id") + "-container").parent().removeClass(errorClass);
         } else {
             elem.removeClass(errorClass);
         }
     },
     errorPlacement: function(error, element) {
       var elem = $(element);
       if (elem.hasClass("select2-hidden-accessible")) {
           element = $("#select2-" + elem.attr("id") + "-container").parent(); 
           error.insertAfter(element);
       } else {
           error.insertAfter(element);
       }
     }
   });

$('select').select2({}).on("change", function (e) {
  $(this).valid()
});
</script>
Adam
  • 25,960
  • 22
  • 158
  • 247
  • If I'm not mistaken, "unhighlight" has been replaced by "success" in the newest version of the jQuery Validate script. I also had to change the if statement in the "unhighlight" section to the following: `if (elem.parent().hasClass("select2")) {` Because the `select2-hidden-accessible` class seems to disappear if a field is invalid. This is using the most recent versions of everything. – dearsina Jan 12 '18 at 18:16
  • I would add that if you have a `background-color` or some CSS that Select2 overrides, you need to add `!important` to your `error` CSS styles. I had a `background-color: yellow` for `error` and Select2 was overriding that. – gene b. Jan 23 '18 at 15:02
  • @dearsina no, unhighliht and success are still distinct from one to another as described in https://jqueryvalidation.org/validate/ – nicolallias Dec 05 '18 at 14:07
17

I have detailed this in a blog post: http://chadkuehn.com/jquery-validate-select2/

When you place a Select2 on a SELECT tag it hides the original element. So in the validation plugin you must adjust the proper wrapping markup when highlighting and unhighlighting.

    highlight: function (element, errorClass, validClass) {
        var elem = $(element);
        if (elem.hasClass("select2-offscreen")) {
            $("#s2id_" + elem.attr("id") + " ul").addClass(errorClass);
        } else {
            elem.addClass(errorClass);
        }
    },

    unhighlight: function (element, errorClass, validClass) {
        var elem = $(element);
        if (elem.hasClass("select2-offscreen")) {
            $("#s2id_" + elem.attr("id") + " ul").removeClass(errorClass);
        } else {
            elem.removeClass(errorClass);
        }
    }

View a DEMO here.

2Yootz
  • 3,971
  • 1
  • 36
  • 31
15

Found an answer on the forums @ https://github.com/select2/select2/issues/215 posted by corinnaerin. Worked perfectly for me. Sample code at http://plnkr.co/edit/4QaSguIiYsJtLpuPF8Rc?p=preview

      var $select = $('select').select2({
        placeholder: 'Choose',
        allowClear: true
      });

      /*
       * When you change the value the select via select2, it triggers
       * a 'change' event, but the jquery validation plugin
       * only re-validates on 'blur'
       */
      $select.on('change', function() {
        $(this).trigger('blur');
      });

      $('#myForm').validate({
        ignore: 'input[type=hidden], .select2-input, .select2-focusser'
      });
Himanshu Patel
  • 754
  • 8
  • 13
5

I've found that getting Select2 to work with jQuery Validate very much depends on the markup used in creating the Select2 control.

For the most practical use of the plugin, you'll probably be using dynamically loaded data (data obtained via web service vs. static <option/> elements in the page). And per their spec, the way to accomplish this is by attaching Select2 to an <input type="hidden"/> element. However, elements of type="hidden" are not validated by jQuery Validate by default.

In order to validate hidden elements using jQuery Validate, one must tinker with the ignore property in jQuery Validate's configuration object. See the ignore option in their spec. Try initializing the ignore value as null to get the validation to trigger.

Ken
  • 1,830
  • 3
  • 20
  • 32
  • My current strategy has been to assign the ignore property to a class named "ignore-validation" like so: ignore: '.ignore-validation' Doing it this way enables you to turn validation on and off for a particular element at will simply by adding/removing that class name on the input element. – Ken Mar 13 '15 at 20:20
3

just add a line in your validation function.

$('#_form_id').validate({

       ignore: 'input[type=hidden]',
            rules: {
                //Rules
            },
            messages: {
               //messages
            },
}
Kristijan Iliev
  • 4,901
  • 10
  • 28
  • 47
Nirav Thakar
  • 166
  • 1
  • 10
2

check out my code. I solve my problem by using those codes... few(css,jquery) codes only

$(document).ready(function() {

  //form validations---------------------------------------------------------
  $('#sample').validate({
    ignore: [],
    errorClass: "error",
    errorElement: "span"
  });

  $("#receiver_name").select2({
    placeholder: "Receiver Name"
  });

  $("#receiver_name").select2().change(function() {
    $(this).valid();
  });
});
.error .select2-choice.select2-default,
.error .select2-choices {
  color: #a94442;
  border-color: #a94442;
  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
}
.error:focus,
.error .select2-choice.select2-defaultLfocus,
.error .select2-choicesLfocus {
  border-color: #843534;
  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;
}
.select2-container .select2-choices .select2-search-field input,
.select2-container .select2-choice,
.select2-container .select2-choices,
.error {
  border-radius: 1px;
}
<html>

<head>
  <!-- Latest compiled and minified CSS -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">

  <!-- Optional theme -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">

  <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.css" rel="stylesheet" />

  <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2-bootstrap.css" rel="stylesheet" />


</head>

<body>
  <form id='sample'>
    <select class="form-control" name="receiver_name[]" id="receiver_name" multiple required>
      <option value="1">1</option>
      <option value="2">2</option>
    </select>
  </form>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

  <!-- Latest compiled and minified JavaScript -->
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.js"></script>


</body>

</html>
2

This doesn't work in Bootstrap Validator() because the validator includes all the inputs in the form. This means it will validate the input search field of the select2 plugin. which will interfere with the multiselect validation

To fix this simply go to the validator.js Add the select2 input search class .select2-search__field to the ignore list:

Validator.INPUT_SELECTOR = ':input:not([type="submit"], button, .select2-search__field):enabled:visible'
0

When you create a custom rule, you also must properly declare it. Since your custom rule depends on an argument, then you must pass the argument when declaring the rule

rules: {
   country: {
       required: true,
       requiredcountry: "your argument here"  // <- declare the custom rule
   }
}
Sparky
  • 98,165
  • 25
  • 199
  • 285
0
$("select.select2-me").each(function(index, el) {

    if ($(this).is("[data-rule-required]") && 
    $(this).attr("data-rule-required") == "true") {
        $(this).on('select2-close', function(e) {
            $(this).valid()
        });
    }
});

work for me.

0

You can check this link: https://github.com/rkeshmir/select2-validation Here you can find the simplest way to validate select2 components. The idea id trigger validation for all <select> items in DOM on their change event. Also I have added required CSS rules to highlight error and success states of input.

RezKesh
  • 2,861
  • 2
  • 24
  • 35
0

To validate 'select2' inputs you first must tell jquery validate to consider hidden elements:

$.validator.setDefaults({ 
ignore: [],
});

This is custom highlight / unhighlight that i use for pointing select2 and tagit errors with jquery validate:

$("#someform").validate({
        rules: {
            nazwa: {
                required: true
            },
            ilosc_w_opakowaniu: {
                required: "#czy_opakowanie_zbiorcze:checked"
            }
        },
        messages: {
            nazwa: "Musisz wypełnić pole [Nazwa]",
            ilosc_w_opakowaniu: "Musisz podać ilość produktu w opakowaniu zbiorczym",
        },

        highlight: function( element, errorClass, validClass ) {
            if ( element.type === "radio" ) {
                this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
            } else {
                $( element ).addClass( errorClass ).removeClass( validClass );
            }

            // select2
            if( $(element).hasClass('select2-hidden-accessible') ){
                dzik = $(element).next('span.select2');
                if(dzik)
                    dzik.addClass( errorClass ).removeClass( validClass );
            }

            // tagit
            dzik2 = $(element).parent().find('ul.tagit') 
            if( dzik2.length == 1 )
                dzik2.addClass( errorClass ).removeClass( validClass );

        },
        unhighlight: function( element, errorClass, validClass ) {
            if ( element.type === "radio" ) {
                this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
            } else {
                $( element ).removeClass( errorClass ).addClass( validClass );
            }

            // select2
            if( $(element).hasClass('select2-hidden-accessible') ){
                dzik = $(element).next('span.select2');
                if(dzik)
                    dzik.removeClass( errorClass ).addClass( validClass );
            }

            // tagit
            dzik2 = $(element).parent().find('ul.tagit') 
            if( dzik2.length == 1 )
                dzik2.removeClass( errorClass ).addClass( validClass );
        }
     });

And some CSS:

/** select2 error hightight **/
.select2.error .select2-selection--single{
    border-color:red !important;
    color:red !important;
}

/** tagit error highlight **/
.tagit.error{
   border-color:red !important;
   color:red !important;
}
denesis
  • 73
  • 5
0

I solved the problem, the solution is to modify the highlight, unhighlight and above all errorPlacement methods for each instance of validate. However, in order not to modify each file, I put the modifications in the file jquery.validate.js

highlight: function( element, errorClass, validClass ) {
        if ( element.type === "radio" ) {
            this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
        } else {
            var elem = $(element);
            if (elem.attr('readonly') == 'readonly') {
                if (elem.hasClass("input-group-addon")) {
                   $("#" + elem.attr("id")).parent().addClass(errorClass);
                } else {
                    $( element ).addClass( errorClass ).removeClass( validClass );
                }
            } else {
                if (elem.hasClass("select2-hidden-accessible")) {
                   $("#select2-" + elem.attr("id") + "-container").parent().addClass(errorClass);
                } else {
                    $( element ).addClass( errorClass ).removeClass( validClass );
                }
            }
        }
    },
    unhighlight: function( element, errorClass, validClass ) {
        if ( element.type === "radio" ) {
            this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
        } else {
            var elem = $(element);
            if (elem.attr('readonly') == 'readonly') {
                if (elem.hasClass("input-group-addon")) {
                   $("#" + elem.attr("id")).parent().removeClass(errorClass);
                } else {
                    $( element ).addClass( errorClass ).removeClass( validClass );
                }
            } else {
                if (elem.hasClass("select2-hidden-accessible")) {
                    $("#select2-" + elem.attr("id") + "-container").parent().removeClass(errorClass);
                } else {
                    $( element ).removeClass( errorClass ).addClass( validClass );
                }
            }
        }
    },
    errorPlacement: function(error, element) {
        var elem = $(element);
        if (elem.attr('readonly') == 'readonly') {
            element = $("#" + elem.attr("id")).parent();
            error.insertAfter(element);
        } else {
            if (elem.hasClass("select2-hidden-accessible")) {
                element = $("#select2-" + elem.attr("id") + "-container").parent().parent().parent();
                error.insertAfter(element);
            } else {
                error.insertAfter(element);
            }
        }
    }
0

According to the error placement logic of jQuery validator, you may use the markup like below.

<div class="input-group col-sm-12">
  <select class="form-control select2" id="ELEMENT ID" name="ELEMENT NAME">
  </select>
</div>

It will place the error block below the select2 box and make the error block visible.

AnkitK
  • 388
  • 3
  • 10