Since my recent post for jQuery TE Validation seems to be popular ( at least for my site 🙂 ) I thought I would demonstrate how to validate another plugin that doesn’t work right out the gate. I’m referring to the Select2 plugin. It is a jQuery replacement for SELECT boxes with a BootStrap type of look. It can product a listbox similar to Facebook’s popular multi-select style. Other options include list item images, searching, sorting (with drag & drop), infinite scrolling, and much more. We will be validating it with the jQuery Validation plugin.
This example uses the following external sources. All of them can be referenced through a Content Delivery Network:
1 2 3 4 5 6 7 8 9 10 11 12 |
<link rel='Stylesheet' type='text/css' href='//cdnjs.cloudflare.com/ajax/libs/select2/3.4.6/select2.css' /> <script type='text/javascript' src='//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js'></script> <script type='text/javascript' src='//cdnjs.cloudflare.com/ajax/libs/select2/3.4.6/select2.js'></script> <script type='text/javascript' src='//cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.12.0/jquery.validate.js'> </script> |
Alternatively, you can go to the plugin sites and retrieve the individual files, or simply install nugets if using .NET.
Now let’s add some markup to the page. The code below covers Select2s that are made in a traditional sense with SELECT tags. If you are creating Select2s with dynamic options (which uses an INPUT[HIDDEN] instead) then I have solution as well. See the second DEMO at the bottom of this tutorial. Here, I’m creating a form with three different types of elements to validate. Each of them have the "required" class which is auto-detected by the jQuery validation plugin. Of course you’re mainly concerned with Select2 but the additional fields are good for a visual comparison when validation fails.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<form id='frm'> <h1>Sample form</h1> <div> <label for='txtName' class='bold block'>Name:</label> <input type='text' name='txtName' id='txtName' class='required' /> </div> <br /> <div> <label for='txtBio' class='bold block'>Bio:</label> <textarea cols='25' rows='4' name='txtBio' id='txtBio' class='required'> </textarea> </div> <br /> <div> <label for='lstColors' class='bold block'>Favorite Colors:</label> <select name='lstColors' id='lstColors' size='1' multiple='multiple' class='required'> <option value='R'>Red</option> <option value='W'>White</option> <option value='B'>Blue</option> </select> </div> <br /> <br /> <input type='submit' value='Submit' /> </form> |
Now let’s add some CSS. Most of this is basic styling besides the myErrorClass portions, which are used to handle validation errors. In our jQuery Validation script we will set it to be our error class. If something fails it will put that class on both the element and an error label. In our script we manipulate the error label to appear behind our element. The !important keyword is needed to override default select2 styling. If all goes well then users should see a striped background on invalid elements as well as a red message describing the error in more detail beneath it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
.bold { font-weight:bold; } .block { display:block; } input[type=text] { width:300px; } body { background-color: #fff; font-size: .80em; font-family:'Helvetica Neue', 'Lucida Grande', Arial; margin: 0px; padding: 0px; color: #696969; } label.myErrorClass { color: red; font-size: 11px; display: block; } ul.myErrorClass input { color: #666 !important; } ul.myErrorClass, input.myErrorClass, textarea.myErrorClass, select.myErrorClass { border-width: 1px !important; border-style: solid !important; border-color: #cc0000 !important; background-color: #f3d8d8 !important; background-position: 50% 50% !important; background-repeat: repeat !important; background-image: url(http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/blitzer/images/ui-bg_diagonals-thick_75_f3d8d8_40x40.png) !important; } |
And finally we add the script. I’ve placed comments throughout to explain the various components:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
$(document).ready(function () { //Transforms the listbox visually into a Select2. $('#lstColors').select2({ placeholder: 'Select a Color', width: '200px' }); //Initialize the validation object which will be called on form submit. var validobj = $('#frm').validate({ onkeyup: false, errorClass: 'myErrorClass', //put error message behind each form element errorPlacement: function (error, element) { var elem = $(element); error.insertAfter(element); }, //When there is an error normally you just add the class to the element. // But in the case of select2s you must add it to a UL to make it visible. // The select element, which would otherwise get the class, is hidden from // view. highlight: function (element, errorClass, validClass) { var elem = $(element); if (elem.hasClass('select2-offscreen')) { $('#s2id_' + elem.attr('id') + ' ul').addClass(errorClass); } else { elem.addClass(errorClass); } }, //When removing make the same adjustments as when adding unhighlight: function (element, errorClass, validClass) { var elem = $(element); if (elem.hasClass('select2-offscreen')) { $('#s2id_' + elem.attr('id') + ' ul').removeClass(errorClass); } else { elem.removeClass(errorClass); } } }); //If the change event fires we want to see if the form validates. //But we don't want to check before the form has been submitted by the user //initially. $(document).on('change', '.select2-offscreen', function () { if (!$.isEmptyObject(validobj.submitted)) { validobj.form(); } }); //A select2 visually resembles a textbox and a dropdown. A textbox when //unselected (or searching) and a dropdown when selecting. This code makes //the dropdown portion reflect an error if the textbox portion has the //error class. If no error then it cleans itself up. $(document).on('select2-opening', function (arg) { var elem = $(arg.target); if ($('#s2id_' + elem.attr('id') + ' ul').hasClass('myErrorClass')) { //jquery checks if the class exists before adding. $('.select2-drop ul').addClass('myErrorClass'); } else { $('.select2-drop ul').removeClass('myErrorClass'); } }); }); |
That’s it! With these adjustments Select2 will have the same look and feel as the rest of your form elements when validating. Leave me a one-liner if you found this useful.
See a DEMO. View this DEMO if loading options dynamically. If this post has helped you then upvote my answer on StackOverflow.
Thanks.