问题
Is it possible to configure Parsley.js to display its error messages both... a) next to individual fields, AND b) in a combined list elsewhere on the page ...at the same time?
Also, is it possible to render error messages with a hyperlink back to the field that generated the error?
Thanks.
UPDATE:
The accepted answer is a fantastic example (thanks milz!) but it needed a bit more refining.
For the benefit of other readers, here's my updated code in which...
Error messages no longer duplicate after failing first validation (in original example, try generating an error then repeatedly pressing backspace in a field - a new message is added to the list for every keystroke)
Error message take the text of the LABEL in the same form-group (handy for radios and checkboxes which don't have individual labels that are meaningful)
Error messages are removed from the list on the fly when they're fixed by the user.
Entire error panel has a title, and is hidden/shown depending on whether it has content or not.
Bootstrap styling, layout & parsley config provided.
In response to Adrian Rodriguez' question about displaying the messages ABOVE the fields, you can change the location of Parsley's default error messages with the following 2 steps:
// A. CHANGE the 'errorsContainer' callback to...
errorsContainer: function(el) {
return el.$element.closest(".control").find(".top"); // Errors will be placed inside the 'div.control > div.top' elements.
}
// B. Additionally, you will either need to manually add '<div class='top'></div>'
// wherever you want the errors to appear. Alternatively, use a little
// JQuery to add these elements to the whole form, as follows...
// 1.5 PREPEND each .control div with a new container for errors
$(".control").prepend("<div class='top'></div>");
// 2. Parslify the form...
etc.
// 1. Configure Parsley for Bootstrap 3 Forms
//
window.ParsleyConfig = {
successClass: "has-success",
errorClass: "has-error",
classHandler: function(el) {
return el.$element.closest(".form-group");
},
errorsContainer: function(el) {
return el.$element.closest(".control");
},
errorsWrapper: "<span class='help-block parsley-messages'></span>",
errorTemplate: "<span></span>"
};
// 2. Parslify the form...
$("#theForm").parsley();
// 3. Configure Parsley to display combined validation-errors-list
//
$(function() {
// Convenience members
$.validationErrors = {
container: $('div.validation-errors-container'),
list: $('div.validation-errors-container ul.validation-errors-list'),
updateContainer: function() {
// Hide/show container if list is empty/full
$.validationErrors.container.toggleClass("filled", $.validationErrors.list.find("li:first").length > 0);
},
removeItem: function(sFieldName) {
// Remove related error messages from list
$.validationErrors.list.find('li[data-related-field-name="' + sFieldName + '"]').remove();
}
};
// NB: Event names pertain to Parsley V2.0
// Before each validation, clear the validation-errors of the div
$.listen('parsley:form:validate', function() {
$.validationErrors.list.html();
});
// When a field has an error
$.listen('parsley:field:error', function(fieldInstance) {
var fieldName = fieldInstance.$element.attr('name');
$.validationErrors.removeItem(fieldName);
// Get the error messages
var messages = ParsleyUI.getErrorsMessages(fieldInstance);
// Loop through all the messages
for (var i in messages) {
// Create a message for each error
var fieldLabel = fieldInstance.$element.closest(".form-group").find("label:first");
var fieldLabelText = fieldLabel.clone().children().remove().end().text().trim();
var fieldName = fieldInstance.$element.attr("name");
var $m = $('<li data-related-field-name="' + fieldName + '"><a data-related-field-name="' + fieldName + '" href="#na"><strong>' + fieldLabelText + '</strong> - ' + messages[i] + '</a></li>');
$.validationErrors.list.append($m);
}
$.validationErrors.updateContainer();
});
$.listen('parsley:field:success', function(fieldInstance) {
$.validationErrors.removeItem(fieldInstance.$element.attr('name'));
$.validationErrors.updateContainer();
});
// When there's a click on a error message from the div
$(document).on('click', 'a[data-related-field-name]', function() {
// take the field's name from the attribute
var name = $(this).attr('data-related-field-name');
$("[name=" + name + "]:first").focus();
});
});
body {
padding: 10px;
}
/* PARSLEY FORM VALIDATION */
/* ensure field-spans injected by parsley don't take up space when empty... */
.parsley-messages {
display: none;
}
.parsley-messages.filled {
display: block;
}
/* aggregated parsley error message display... */
div.validation-errors-container {
display: none;
}
div.validation-errors-container.filled {
display: block;
}
div.validation-errors-container ul.validation-errors-list {
margin: 0;
padding: 0;
}
div.validation-errors-container ul.validation-errors-list li {
color: rgb(169, 68, 66);
list-style: outside none disc;
margin-left: 16px;
padding-left: 1em;
text-indent: -0.7em;
}
div.validation-errors-container ul.validation-errors-list li a {
color: inherit;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/parsley.js/2.0.7/parsley.min.js"></script>
<!-- VALIDATION ERRORS CONTAINER -->
<div class="validation-errors-container panel panel-danger" role="alert" aria-labelledby="validation-errors-heading" aria-live="assertive">
<div class="panel-heading" id="validation-errors-heading"><strong>Alert!</strong> Please correct the following errors...</div>
<div class="panel-body">
<ul class="validation-errors-list"></ul>
</div>
</div>
<!-- BOOTSTRAP 3 FORM -->
<form class="form-horizontal" id="theForm">
<div class="form-group">
<label class="control-label col-xs-2">
Name <span class="required-indicator" title="Required">*</span>
</label>
<div class="control col-xs-10">
<input type="text" name="userName" class="form-control" data-parsley-required="true">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-2">
Gender <span class="required-indicator" title="Required">*</span>
</label>
<div class="control col-xs-10">
<label class="checkbox-inline">
<input type="radio" data-parsley-required="true" name="gender" value="F" />Girl
</label>
<label class="checkbox-inline">
<input type="radio" name="gender" value="M" />Boy
</label>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-2">
Email <span class="required-indicator" title="Required">*</span>
</label>
<div class="control col-xs-10">
<input type="text" name="userEmail" class="form-control" data-parsley-type="email" data-parsley-required="true">
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
回答1:
To accomplish what you want, you need to use Parsley's events. Take a look at the event's description and the comments on the below code.
<div class="validation-errors"></div>
<form>
<input type="text" name="field1" required />
<input type="text" name="field2" required />
<input type="submit" />
</form>
<script>
$(document).ready(function() {
// validate form
$("form").parsley();
// Before each validation, clear the validation-errors of the div
$.listen('parsley:form:validate', function() {
$('.validation-errors').html('');
});
// When a field has an error
$.listen('parsley:field:error', function(fieldInstance){
// Get the error messages
var messages = ParsleyUI.getErrorsMessages(fieldInstance);
// Get the field's name
var fieldName = fieldInstance.$element.attr('name');
// Loop through all the messages
for (var i in messages) {
// Create a message for each error
var $m = $('<p><a class="focus-' + fieldName + '" href="#">' + fieldName + ': ' + messages[i] + '</a><p>');
// Append the errors to the div
$('.validation-errors').append($m);
}
});
});
// When there's a click on a error message from the div
$(document).on('click', 'a[class^="focus-"]', function(){
// take the field's name from the class
var parts = $(this).attr('class').split('-');
$("[name=" + parts[1] + "]").focus();
});
</script>
Here's a demo in Jsfiddle.
Important note: the code I'm providing uses the events available in Parsley 2.0.* . If you're using the newly Parsley 2.1.*, you should use the correct events. Instead of parsley:form:validate
use form:validate
and replace parsley:field:error
by field:error
.
来源:https://stackoverflow.com/questions/31173916/parsley-js-display-errors-near-fields-and-in-a-combined-list-above-form