81

I have some <select> inputs using the chosen plugin that I want to validate as "required" on the client side. Since "chosen" hides the actual select element and creates a widget with divs and spans, native HTML5 validation doesn't seem to work properly. The form won't submit (which is good), but the error message is not shown, so the user has no idea what's wrong (which is not good).

I've turned to the jQuery validation plugin (which I planned on using eventually anyways) but haven't had any luck so far. Here's my test case:

<form>
    <label>Name: <input name="test1" required></label>
    <label>Favorite Color:
        <select name="test2" required>
            <option value=""></option>
            <option value="red">Red</option>
            <option value="blue">Blue</option>
            <option value="green">Green</option>
        </select>
    </label>
    <input type="submit">
</form>
$(document).ready(function(){
    $('select').chosen();
    $('form').validate();
});

This is letting the select through with an empty value, without validating or showing the error message. When I comment out the chosen() line, it works fine.

How can I validate chosen() inputs with the jQuery validation plugin, and show the error message for invalid ones?

Wesley Murch
  • 101,186
  • 37
  • 194
  • 228
  • 1
    Check [this plugin](https://github.com/elclanrs/jq-idealforms) out. Not really a solution but you might want to give it a try. – elclanrs Jun 27 '12 at 18:04
  • @elclanrs: Thanks but I'd like to stick with the de facto jQuery validation library for now, especially at this point in the project (trying to wrap up). Maybe in a future project. – Wesley Murch Jun 27 '12 at 18:11
  • This post solved my problem: http://stackoverflow.com/questions/10387553/chosen-js-and-validate-jquery Simple and elegant. –  Oct 09 '12 at 02:21

18 Answers18

128

jQuery validate ignores the hidden element, and since the Chosen plugin adds visibility:hidden attribute to the select, try:

$.validator.setDefaults({ ignore: ":hidden:not(select)" }) //for all select

OR

$.validator.setDefaults({ ignore: ":hidden:not(.chosen-select)" }) //for all select having class .chosen-select

Add this line just before validate() function. It works fine for me.

pb2q
  • 58,613
  • 19
  • 146
  • 147
Anupal
  • 1,502
  • 2
  • 11
  • 15
  • 1
    This was quite sufficient in my case. Thanks. – Nick Jul 10 '13 at 05:25
  • 1
    Where did you put this line? It doesn't seem to work for me :/ – Charles Wood Dec 19 '13 at 22:16
  • 1
    just above the JQuery validate() function. – Anupal Dec 21 '13 at 07:49
  • 1
    Worked for me! Definitely the simplest solution. – kmgdev Feb 13 '14 at 18:57
  • 7
    Because all my chosen selects have the class `.chosen-select` I find it better to use `$.validator.setDefaults({ ignore: ":hidden:not(.chosen-select)" });`. Otherwise this would mean all hidden selects would be validated. – Tobias Nov 28 '14 at 11:09
  • 1
    Works perfectly! I added it in my header with `` and works good – Benjamin RD Jan 23 '15 at 19:58
  • 1
    @Anupal: this code seems to work perfectly if you have only a single panel with chosen enabled elements. I have two panels which both have a chosen enabled element and this line does not work for me `form.validate().settings.ignore = ":disabled,:hidden:not('select.chosen-select')"` – Lorenzo Aug 31 '15 at 12:21
  • 1
    I have 2 chosen selects within a form and the first option worked for me, while the second did not. – Nando Feb 27 '16 at 21:22
  • 1
    Perfect! Was looking out for this since ages :) – Chetan Gawai Apr 01 '16 at 10:54
  • 1
    hello guys, I have a problem with the focus of **jqueryvalidation**, doesn't work on the **chosen** fields, do you know how solve that problem ? – Paul Noris Jul 23 '17 at 20:26
19

jQuery validation isn't going to pick up elements that are hidden, but you can force it to validate individual elements. Bit of a hack, but the following will work:

$('form').on('submit', function(e) {
    if(!$('[name="test2"]').valid()) {
        e.preventDefault();
    }
});  

To select only "chosen" elements you can use $('.chzn-done')

Wesley Murch
  • 101,186
  • 37
  • 194
  • 228
Mike Robinson
  • 24,971
  • 8
  • 61
  • 83
  • 2
    It seems that the `e.preventDefault()` isn't even necessary, just calling `$("element").valid()`. I used [this code](http://jsfiddle.net/mrZF5/5/) and it seems to work perfectly: `$('form').on('submit', function() {$('.chzn-done').valid();});`. Thanks for the info. – Wesley Murch Jun 27 '12 at 19:03
  • 4
    `.chzn-done` is no longer added to "chosen" elements as of Chosen 1.0 – Sebastian Zaklada Oct 07 '13 at 09:40
5

in mine.

my form has class 'validate' and every input element has class 'required' html code:

<form id="ProdukProdukTambahForm" class="validate form-horizontal" accept-charset="utf-8" method="post" enctype="multipart/form-data" action="/produk-review/produk/produkTambah" novalidate="novalidate">
     <div class="control-group">
        <label class="control-label" for="sku">SKU</label>
        <div class="controls">
           <input id="sku" class="required span6" type="text" name="sku">
        </div>
     </div>
     <div class="control-group">
        <label for="supplier" class="control-label">Supplier</label>
        <div class="controls">
            <select name="supplier" id="supplier" class='cho span6 {required:true} '>                                           
                <option value=''>-- PILIH --</option>
                <?php
                foreach ($result as $res)
                    {
                    echo '<option value="'.$res['tbl_suppliers']['kode_supplier'].'">'.$res['tbl_suppliers']['nama_supplier'].'</option>';
                    }
                ?>
            </select>
         </div>
      </div>
</form>

and javascript code for choosen with jquery validation

$(document).ready(function() {
    // - validation
    if($('.validate').length > 0){
        $('.validate').validate({
            errorPlacement:function(error, element){
                    element.parents('.controls').append(error);
            },
            highlight: function(label) {
                $(label).closest('.control-group').removeClass('error success').addClass('error');
            },
            success: function(label) {
                label.addClass('valid').closest('.control-group').removeClass('error success').addClass('success');
            },
            //validate choosen select (select with search)
            ignore: ":hidden:not(select)"
        });
    }
    // - chosen, add the text if no result matched
    if($('.cho').length > 0){
        $(".cho").chosen({no_results_text: "No results matched"});
    }
});

note: if the input value is null, the class error will be append to parent 'div'

Acang Terpal
  • 51
  • 1
  • 1
3

//You can fix this by using another way to hide your chosen element. eg....

$(document).ready(function() {
 $.validator.addMethod(     //adding a method to validate select box//
            "chosen",
            function(value, element) {
                return (value == null ? false : (value.length == 0 ? false : true))
            },
            "please select an option"//custom message
            );

    $("form").validate({
        rules: {
            test2: {
                chosen: true
            }
        }
    });
    $("[name='test2']").css("position", "absolute").css("z-index",   "-9999").chosen().show();

    //validation.....
    $("form").submit(function()
    {
        if ($(this).valid())
        {alert("valid");
    //some code here 
        }
        return false;

    });
});
vikrant singh
  • 2,091
  • 1
  • 12
  • 16
  • This answer only works if you don't call .chosen(). There seems to be a bug (feature?) in the chosen library that when you activate a – Zack Morris Feb 04 '13 at 20:12
2

this simple CSS rule works on joomla 3's implementation of chosen

Chosen adds the class invalid to the hidden select input so use this to target the chosen select box

.invalid, .invalid + div.chzn-container a {
    border-color: red !important;
}
philip
  • 403
  • 1
  • 4
  • 14
  • In my case, I've added **ul.chosen-choices**: `.input-validation-error { border-color: red !important; } .input-validation-error, .input-validation-error + div.chosen-container ul.chosen-choices { border-color: red !important; }`. – pas Oct 03 '19 at 08:20
2

I had to place $.validator.setDefaults({ ignore: ":hidden:not(.chosen-select)" })
outside $(document).ready(function()) in order to work with chosen.js.

https://stackoverflow.com/a/10063394/4063622

Tobi G.
  • 1,530
  • 2
  • 13
  • 16
1

You might also running into trouble that error message is displayed before Chosen dropdownlist. I found out the solution to resolve this issue and paste my code here to share with you

HTML:

<label class="col-sm-3">Select sponsor level *</label>
<asp:DropDownList ID="ddlSponsorLevel" runat="server" CssClass="col-sm-4 required" ClientIDmode="Static" />
<label class="error" id="ddlSponsorLevel-error" for="ddlSponsorLevel"></label>

Javascript:

if (!$('#ddlSponsorLevel').valid()) {
       $('#ddlSponsorLevel-error').text("You must choose a sponsor level");
            return false;
}

Jquery Validation actually added a hidden label html element. We can re-define this element with same ID on different place to overwrite original place.

Gavin Tian
  • 11
  • 1
1

I spent about a day working on this and had no luck at all! Then I looked at the source code Vtiger was using and found gold! Even though they were using older versions they had the key! you have to use

data-validation-engine="validate[required]"

If you don't and you have it where classes are passed through the class for the select gets applied to the chosen and it thinks that your chosen never gets updated. If you don't pass the class onto the chosen this should be a problem, BUT if you do this is the only way it will work.

This is with chosen 1.4.2 validationEngine 2.6.2 and jquery 2.1.4

// binds form submission and fields to the validation engine
jQuery("#FORMNAME").validationEngine({
    prettySelect : true,
    useSuffix: "_chosen"
    //promptPosition : "bottomLeft"
});
Tamil Selvan C
  • 19,913
  • 12
  • 49
  • 70
Mav2287
  • 796
  • 2
  • 9
  • 22
1

@Anupal put me on the right path but somehow I needed a complex fix

Enable .chosen to be considered

javascript

$.validator.setDefaults({ ignore: ":hidden:not(.chosen)" })

Or any other name you give to your chosen's. This is global configuration. Consider setting on top level

Create custom rule for chosen

Thanks to BenG

html

<select id="field" name="field" class="chosen" data-rule-chosen-required="true">
    <option value="">Please select…</option>
</select>

javascript

Again, global configuration for $.validator object. Can be put next to the previous command

$.validator.addMethod('chosen-required', function (value, element, requiredValue) {
    return requiredValue == false || element.value != '';
}, $.validator.messages.required);
Community
  • 1
  • 1
Alwin Kesler
  • 1,450
  • 1
  • 20
  • 41
0

I think this is the better solution.

//trigger validation onchange
$('select').on('change', function() {
    $(this).valid();
});

$('form').validate({
    ignore: ':hidden', //still ignore Chosen selects
    submitHandler: function(form) { //all the fields except Chosen selects have already passed validation, so we manually validate the Chosen selects here            
        var $selects = $(form).find('select'),
            valid = true;
        if ($selects.length) {
            //validate selects
            $selects.each(function() {
                if (!$(this).valid()) {
                    valid = false;
                }
            });
        }
        //only submit the form if all fields have passed validation
        if (valid) {
            form.submit();
        }
    },
    invalidHandler: function(event, validator) { //one or more fields have failed validation, but the Chosen selects have not been validated yet
        var $selects = $(this).find('select');     
        if ($selects.length) {
            validator.showErrors(); //when manually validating elements, all the errors in the non-select fields disappear for some reason

            //validate selects
            $selects.each(function(index){
                validator.element(this);
            })
         }
    },
    //other options...
});

Note: You will also need to change the errorPlacement callback to handle displaying the error. If your error message is next to the field, you will need to use .siblings('.errorMessageClassHere') (or other ways depending on the DOM) instead of .next('.errorMessageClassHere').

noypiscripter
  • 1,451
  • 1
  • 13
  • 13
0
jQuery("#formID").validationEngine({
     prettySelect : true,
     useSuffix: "_chzn"
});

jQuery-Validation-Engine/demoChosenLibrary

zk_mars
  • 1,339
  • 2
  • 15
  • 36
dsmoreira
  • 1
  • 1
0

You can also try this:

$('form').on('submit', function(event) {
    event.preventDefault();
    if($('form').valid() == true && $('.select-chosen').valid() == true){
        console.log("Valid form");
    } else {
        console.log("Invalid form");
    }
}); 

Remember to add .select-chosen class on each selects.

$('.select-chosen').valid() forces the validation for the hidden selects

http://jsfiddle.net/mrZF5/39/

Fred K
  • 13,249
  • 14
  • 78
  • 103
0

My form includes conditionally hidden fields, to prevent the hidden chosen fields failing validation I've extended the default ignore:hidden a little further:

$.validator.setDefaults({ 
  ignore: ":hidden:not(.chosen-select + .chosen-container:visible)"  //for all select having class .chosen-select
    })
ecolema
  • 588
  • 4
  • 15
  • Doesn't work for me at all. The `.chosen-select + .chosen-container:visible` part actually selects the chosen's `
    ` and not the `
    – jlh Jan 25 '17 at 08:55
0

In the year 2018 I am verifying that jQuery validate is complaining about an input field with no name. This input field is appended by the jQuery Chosen plguin.

enter image description here

This bug is happening before anything else when using chosen.

MarkSkayff
  • 1,334
  • 9
  • 14
0

Thanks this answer https://stackoverflow.com/a/40310699/4700162 i resolve the iussue:

Inside the file the Chosen.jquery.js, change

this.form_field_jq.hide().after(this.container);

with this:

this.form_field_jq.css('position', 'absolute').css('opacity', 0).after(this.container);
faienz93
  • 161
  • 2
  • 18
0

you can use jQuery validation for “chosen” plugin. Working fine for me.

$('.chosen').chosen({
        allow_single_deselect: true
    });
    $.validator.setDefaults({ ignore: ":hidden:not(select)" });
        $('form').validate({
            highlight: function(element) {
                $(element).closest('.form-group').addClass('has-error');
        },
        unhighlight: function(element) {
            $(element).closest('.form-group').removeClass('has-error');
        },
        errorElement: 'span',
        errorClass: 'help-block text-danger',
        errorPlacement: function(error, element) {
            if(element.parent('.input-group').length) {
                error.insertAfter(element.parent());
            } else {
                error.insertAfter(element.parent());
            }
        }
    });
Altaf
  • 11
0

After calling chosen() use below jquery method

$("#id").css("display":"").addClass("sr-only");

sr-only is boot strap class

0

I ended up solving it by doing the following:

This was for Chosen v1.8.7:

  1. Open chosen.js and on line 199 locate this:

this.form_field_jq.hide().after(this.container),

  1. Replace that with this:

this.form_field_jq.addClass('chosen-master').after(this.container),

  1. Add these CSS attributes to that class:
.chosen-master {
  display: inline-block !important;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
}

Reference: https://stackoverflow.com/a/64491538/7353382

Dani Amsalem
  • 1,266
  • 17
  • 26