问题
The context
- I have a form that I'm validating using JQuery Validate Plugin.
- All form controls are required except for the textarea.
- I'm using Bootstrap 3 validation states to style the form controls being validated.
- For the select control, I'm using the Chosen Select Plugin
The problem
I'm having trouble figuring out how to address the following:
1- Prevent the textarea control from being applied the success validation state since this form control is not being validated as it is optional.
(To reproduce the problem in the JSFiddle below, click the Submit button with the empty form)
2- Apply the error validation state to the border of the dropdown list. Right now only the label gets the error validation state applied.
3 - Remove the error validation state and error message, and apply the success class when the user chooses an option from the dropdown list. Right now the error message and error class remain.
A JSFiddle
I created a JSFiddle to illustrate the problems.
The 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>
The 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"
}
});
});
});
I've been struggling with this without any luck. Any help will be greatly appreciated.
回答1:
Prevent the textarea control from being applied the success validation state since this form control is not being validated as it is optional.
The empty
textarea
is "valid" because your validation says an empty field is valid, therefore it's green. You could conditionally usehighlight
andunhighlight
so that it will not be applied to yourtextarea
. However, then it will not work when yourmaxlength
rule is evaluated.I know of no workaround that will causeThere is no "optional" condition/state provided in this plugin... once the form is evaluated, fields are either "valid" or "invalid", nothing in between.unhighlight
to get ignored when the field is technically "valid" and yet still empty.EDIT: You can conditionally apply
highlight
andunhighlight
on thetextarea
using the custom:blank
selector and applying a class to this "optional" element. Then you'll still get the red & green outlines, but only when this "optional" field is filled out and/or your rules are evaluated.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'); } }
Apply the error validation state to the border of the dropdown list. Right now only the label gets the error validation state applied.
You need to look at the rendered DOM and find the dynamically created Chosen element. Then you need to write jQuery to traverse over to this element and conditionally apply the appropriate classes via
highlight
andunhighlight
.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'); }
This code above is applying the
has-error
andhas-success
classes to the rendered Chosendiv
element; you just need to adjust your CSS so that there is a red border. Otherwise, write your own CSS classes for this like I did in the demo below. Adjust accordingly.Remove the error validation state and error message, and apply the success class when the user chooses an option from the dropdown list.
You must write a
change
handler that calls the.valid()
method on theselect
element every time it changes. This is because you are interacting with the rendered select list and not the actualselect
element. Otherwise, the jQuery Validate plugin is not properly triggered.$('.chosen-select').on('change', function () { $(this).valid(); });
DEMO: https://jsfiddle.net/jxvqsodz/7/
来源:https://stackoverflow.com/questions/30548059/bootstrap-3-validation-states-with-jquery-validated-form-that-uses-chosen-plugin