如何让select2与jquery.validation插件一起使用?

49

我正在尝试使用jquery.validation插件验证select2字段,但是没有反应。

我想要将select2设为必填字段。

我正在使用以下自定义验证函数:

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

这是规则:

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

我应该使用哪个select2字段来匹配规则?

我很感谢任何关于如何让select2与jquery.validation一起工作的想法。

10x

15个回答

47

只需在您的表单验证函数中添加ignore: [],,它将启用隐藏字段验证。因此,您将获得Select 2的验证

$("#ContactForm").validate({
  ignore: [],       
  rules: {
    //Rules
  },
  messages: {
    //messages
  }
});

这很简单 - 但在Select2的文档中找不到任何提及 - SolaceBeforeDawn
太棒了,我自己尝试了很长时间后,终于解决了我的问题!+1 - e_i_pi
我刚遇到了同样的问题,如果有人想知道为什么会出现这种情况以及为什么 ignore: [] 可以解决它 - 这是我的故事:
  1. 我将“hidden”类添加到选择器中,该类将 display: none 应用于元素
  2. 这使得验证器将 <select> 解释为 type="hidden"
  3. 默认情况下,它不会被验证
  4. 因此需要使用 ignore: []
- yavor.vasilev
我认为问题出在“hidden”关键字上,而不是CSS样式上,因为当我将类更改为其他内容时,问题就无法再现了。 - yavor.vasilev
1
当我添加了 ignore:[],它进行了验证,但表单没有提交。 - user3653474

33

作为一个提示,请注意validate js绑定自身到select而不是select2的更改。这会在以下情况下导致问题:

  1. 有一个必填的选择框,它被转换成了select2
  2. 你点击提交按钮,错误提示显示需要选择该选择框。
  3. 你从select2中选择了一些选项。
  4. 验证错误没有自动隐藏

您可以使用以下方法进行修复:

     $("select").on("select2:close", function (e) {  
        $(this).valid(); 
    });

$("select").on("select2-close", function (e) {
$(this).valid(); });
- Ferry Meidianto

23

除了ABIRAMAN的回答外,这里还有一些代码:

  • 在错误出现时将select2框标记为红色
  • 在select2框下面列出错误

<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>

如果我没记错的话,在最新版本的jQuery Validate脚本中,“unhighlight”已被“success”替换。我还不得不更改“unhighlight”部分中的if语句,如下所示: if (elem.parent().hasClass("select2")) { 因为如果字段无效,select2-hidden-accessible类似乎会消失。这是使用最新版本的所有内容。 - dearsina
我想补充一点,如果你有一个被Select2覆盖的background-color或其他CSS属性,你需要在你的error CSS样式中添加!important。我曾经为error设置了background-color: yellow,但是Select2覆盖了它。 - gene b.
@dearsina 不,unhighliht和success仍然是彼此不同的,就像https://jqueryvalidation.org/validate/中所描述的那样。 - nicolallias

17

我在一篇博客文章中详细介绍了这个问题:http://chadkuehn.com/jquery-validate-select2/

当你在 SELECT 标签上使用 Select2 时,它会隐藏原来的元素。因此,在验证插件中,您必须在突出显示和取消突出显示时调整正确的包装标记。

    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);
        }
    }

在这里查看演示


1
有没有可能更新Select2 4.0.x版本?它似乎无法正常工作。 - Tsukasa
1
@Tsukasa,你可以在我的回答中找到更新:https://dev59.com/Y2Ag5IYBdhLWcg3wOo79#46953372 - Adam
1
非常感谢@Adam,你的答案至今仍然兼容! - nicolallias

15

在论坛上找到了解决方法,@ https://github.com/select2/select2/issues/215 ,由corinnaerin发布。对我非常有效。示例代码请参见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'
      });

1
$select.on('change', function() { $(this).trigger('blur'); }); 点赞。 - Ahmad Mobaraki
完美的逻辑答案。谢谢。 - Harun ERGUL
正是我所需要的,运行得非常好。谢谢! - user752746

5
我发现让Select2与jQuery Validate配合使用非常依赖于创建Select2控件时使用的标记。对于插件最实用的用法,您可能会使用动态加载的数据(通过Web服务获取的数据而不是页面中的静态

我的当前策略是将 ignore 属性分配给一个名为 "ignore-validation" 的类,如下所示:ignore: '.ignore-validation' 以这种方式进行操作可以让你通过在输入元素上添加/删除该类名来随意打开或关闭特定元素的验证。 - Ken

3
只需要在您的验证函数中添加一行代码即可。
$('#_form_id').validate({

       ignore: 'input[type=hidden]',
            rules: {
                //Rules
            },
            messages: {
               //messages
            },
}

1
很高兴为您效劳,Damith。 - Nirav Thakar

2
这在Bootstrap Validator()中不起作用,因为验证器包括表单中的所有输入。 这意味着它将验证select2插件的输入搜索字段。 这将干扰多选验证。
要解决这个问题,只需进入validator.js 将select2输入搜索类.select2-search__field添加到忽略列表中:
Validator.INPUT_SELECTOR = ':input:not([type="submit"], button, .select2-search__field):enabled:visible'

2

看看我的代码。我使用这些代码解决了我的问题......只使用了少量的(css,jquery)代码

$(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>


0

我解决了这个问题,解决方案是修改每个validate实例的highlight、unhighlight和errorPlacement方法。但是为了不修改每个文件,我将修改放在了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);
            }
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接