Bootstrap 3 个验证状态 JQuery-validated form 使用 Chosen 插件

Bootstrap 3 validation states with JQuery-validated form that uses Chosen plugin

上下文

问题

我不知道如何解决以下问题:

1- 防止将文本区域控件应用到成功验证状态,因为此表单控件未被验证,因为它是可选的。

(要重现下面 JSFiddle 中的问题,请单击带有空表单的提交按钮)

2- 将错误验证状态应用于下拉列表的边框。现在只有标签应用了错误验证状态。

3 - 删除错误验证状态和错误消息,并在用户从下拉列表中选择一个选项时应用成功 class。现在错误消息和错误 class 仍然存在。

一个 JSFiddle

我创建了一个 JSFiddle 来说明问题。

HTML

<div class="container" role="main">
    <!-- Contents of the popover associated with the task name text input -->
    <div id="namePopoverContent" class="hide">
        <ul>
            <li><small>...</small></li>
            <li><small>...</small></li>
        </ul>
    </div>

    <form class="form-horizontal" method="post" action="" id="taskForm">
        <div class="row">
            <div class="col-md-9">
                <div class="form-group">
                    <label for="taskName" class="control-label col-md-1">Name</label>
                    <div class="col-md-11">
                        <input type="text" class="form-control taskNameValidation" id="taskName" name="taskName" autofocus required data-toggle="popover">
                    </div>
                </div>
            </div>
            <div class="col-md-3"></div>
        </div>

        <div class="row">
            <div class="col-md-9">
                <div class="form-group">
                    <label for="taskDataset" class="col-md-1 control-label">Dataset</label>
                    <div class="col-md-11">
                        <select class="form-control chosen-select taskDatasetValidation" data-placeholder="Choose a dataset" name="taskDataset" id="taskDataset" required>
                            <option value=""></option>
                            <option value="runnableDataset_Id1">Dataset 1</option>
                            <option value="runnableDataset_Id2">Dataset 2</option>
                            <option value="runnableDataset_Id3">Dataset 3</option>
                            <option value="runnableDataset_Id4">Dataset 4</option>
                        </select>
                    </div>
                </div>
            </div>
            <div class="col-md-3"></div>
        </div>
        <div class="row">
            <div class="col-md-9">
                <div class="form-group">
                    <label for="taskDescription" class="col-md-1 control-label">Description</label>
                    <div class="col-md-11">
                        <textarea class="form-control" name="taskDescription" id="taskDescription" maxlength="1000" rows="4"></textarea>
                    </div>
                </div>
            </div>
            <div class="col-md-3"></div>
        </div>
        <div class="row">
            <div class="col-md-9">
                <div class="pull-right top-margin">
                    <input type="submit" class="btn btn-primary btn-sm" value="Submit" name="taskSetUpSubmit">
                </div>
            </div>
            <div class="col-md-3"></div>
        </div>
    </form>

JS

//Bootstrap popover
$('[data-toggle="popover"]').popover({ 
    trigger: "hover focus",
    container: "body",
    placement: "bottom",
    html: true,
    title: "Name Tips",
    content: function() { return $('#namePopoverContent').html();}
});

//Chosen select plugin
$(function() {
    $('.chosen-select').chosen();
    $('.chosen-select-deselect').chosen({ allow_single_deselect: true });
});

//JQuery validate plugin
$(function() {
    $.validator.setDefaults({
        errorClass: 'text-danger',
        ignore: ':hidden:not(.chosen-select)',
        errorPlacement: function (error, element) {
            if (element.hasClass('chosen-select'))
                error.insertAfter(element.siblings(".chosen-container"));
            else {
                error.insertAfter(element);
            }
        }
    });

    //rules and messages objects
    $("#taskForm").validate({
        highlight: function(element) {
            $(element).closest('.form-group').removeClass('has-success').addClass('has-error');
        },
        unhighlight: function(element) {
            $(element).closest('.form-group').removeClass('has-error').addClass('has-success');
        }
    });

    $('.taskNameValidation').each(function() {
        $(this).rules('add', {
            required: true,
            messages: {
                required: "Provide a space-separated name"
            }
        });
    });

    $('.taskDatasetValidation').each(function() {
        $(this).rules('add', {
            required: true,
            messages: {
                required: "Choose a dataset"
            }
        });
    });
});

我一直在努力解决这个问题,但没有任何运气。任何帮助将不胜感激。

  1. Prevent the textarea control from being applied the success validation state since this form control is not being validated as it is optional.

    textarea 是 "valid" 因为您的验证表明空字段有效,因此它是绿色的。您可以有条件地使用highlightunhighlight,这样它就不会应用到您的textarea。但是,当您的 maxlength 规则被评估时它将不起作用。 我知道没有解决方法会导致 unhighlight 在技术上 "valid" 但仍然为空时被忽略。 没有 "optional" condition/state 在此插件中提供...一旦对表单进行评估,字段要么是 "valid" 要么是 "invalid",中间没有任何内容。

    编辑:您可以使用自定义 :blank [=81] 有条件地在 textarea 上应用 highlightunhighlight =] 或将 class 应用于此 "optional" 元素。然后你仍然会得到红色和绿色的轮廓,但只有当这个 "optional" 字段被填写时 and/or 你的规则才会被评估。

    highlight: function (element) {
        if (! ($(element).hasClass('optional') && $(element).is(':blank'))) {
            $(element).closest('.form-group').removeClass('has-success').addClass('has-error');
        }
    },
    unhighlight: function (element) {
        if (! ($(element).hasClass('optional') && $(element).is(':blank'))) {
            $(element).closest('.form-group').removeClass('has-error').addClass('has-success');
        }
    }
    
  2. Apply the error validation state to the border of the dropdown list. Right now only the label gets the error validation state applied.

    您需要查看呈现的 DOM 并找到动态创建的 Chosen 元素。然后你需要写 jQuery 遍历到这个元素,并通过 highlightunhighlight.

    有条件地应用适当的 classes
    highlight: function (element) {
        if ($(element).hasClass('chosen-select')) {
            $(element).siblings('.chosen-container').removeClass('has-success').addClass('has-error');
        }
        $(element).closest('.form-group').removeClass('has-success').addClass('has-error');
    },
    unhighlight: function (element) {
       if ($(element).hasClass('chosen-select')) {
           $(element).siblings('.chosen-container').removeClass('has-error').addClass('has-success');
       } 
       $(element).closest('.form-group').removeClass('has-error').addClass('has-success');
    }
    

    上面的代码 has-errorhas-success class 应用于呈现的 Chosen div 元素;你只需要调整你的 CSS 这样就有一个红色的边框。否则,就像我在下面的演示中所做的那样,为此编写您自己的 CSS classes。相应调整。

  3. Remove the error validation state and error message, and apply the success class when the user chooses an option from the dropdown list.

    您必须编写一个 change 处理程序,在每次更改时调用 select 元素上的 .valid() 方法。这是因为您正在与呈现的 select 列表而不是实际的 select 元素进行交互。否则,jQuery 验证插件不会正确触发。

    $('.chosen-select').on('change', function () {
        $(this).valid();
    });
    

演示:https://jsfiddle.net/jxvqsodz/7/