Skip to content

Commit da59a16

Browse files
committed
Displaying the first validation error in cleaner way.
1 parent d2c293d commit da59a16

File tree

3 files changed

+39
-37
lines changed

3 files changed

+39
-37
lines changed

dist/bootstrap-angular-validation.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/directives/validation.directive.js

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ angular.module("bootstrap.angular.validation").directive("bsValidation", ["$inte
2828
restrict: "A",
2929
require: "ngModel",
3030
link: function($scope, $element, $attr, ngModelController) {
31+
var errorElementClass = "bs-invalid-msg";
3132
// All classed needed to add to validation message
32-
var errorClasses = ["validation-error", "help-block"];
33-
var searchableClasses = errorClasses.join(",");
33+
var errorClasses = [errorElementClass, "help-block"];
3434
var markupClasses = errorClasses.join(" ");
3535

3636
// Search parent element with class form-group to operate on.
@@ -46,7 +46,13 @@ angular.module("bootstrap.angular.validation").directive("bsValidation", ["$inte
4646
* with the validation key and then fallback to use the default message.
4747
*/
4848
function resolveMessage(element, key) {
49+
/*
50+
* First search if the input element has a custom message for a particular validation key. For example:
51+
* Check if "title-required" attribute is present on the element to display the validation error message
52+
* when the field is required.
53+
*/
4954
var message = element.attr("title-" + key);
55+
5056
if (!message) {
5157
message = bsValidationService.getDefaultMessage(key);
5258

@@ -65,7 +71,7 @@ angular.module("bootstrap.angular.validation").directive("bsValidation", ["$inte
6571
*/
6672
function displayOrHideError() {
6773
/*
68-
* Do not show or hide error for current element don"t have any validation errors or has validation
74+
* Do not show or hide error for current element don't have any validation errors or has validation
6975
* error but user has not attempted to submit the form yet.
7076
*/
7177
if (!$scope.formSubmissionAttempted || !ngModelController.$invalid) {
@@ -77,47 +83,43 @@ angular.module("bootstrap.angular.validation").directive("bsValidation", ["$inte
7783
return false;
7884
}
7985

80-
var oneErrorDisplayed = false;
81-
8286
/**
83-
* Iterate through each error for the current element & display only the first error.
84-
* For multiple validation, this $error object will be like this:
87+
* Display the first error for the current element. For multiple validations, this $error object will
88+
* be like this:
8589
*
8690
* $error = {
8791
* required: true, // When field is marked as required but not entered.
8892
* minlength: true,
8993
* number: false
9094
* }
9195
*/
92-
angular.forEach(ngModelController.$error, function(value, key) {
93-
if (value && !oneErrorDisplayed) {
94-
// Add bootstrap error class
95-
formGroupElement.addClass("has-error");
96-
97-
var message = resolveMessage($element, key);
98-
// Find if the parent class already have error message container.
99-
var errorElement = formGroupElement.findOne("span." + searchableClasses);
100-
var iconMarkup = "<i class=\"fa fa-exclamation-triangle fa-fw\"></i>";
101-
102-
// If not, then append an error container
103-
if (errorElement.length === 0) {
104-
var insertAfter = $element;
105-
// Check if the container have any Bootstrap input group then append the error after it
106-
var groupElement = formGroupElement.findOne(".input-group");
107-
if (groupElement.length > 0) {
108-
insertAfter = groupElement;
109-
}
110-
var errorMarkup = "<span class=\"" + markupClasses + "\">" + iconMarkup + message + "</span>";
111-
insertAfter.after(errorMarkup);
112-
} else {
113-
// Else change the message.
114-
errorElement.html(iconMarkup + message).removeClass("ng-hide");
115-
}
116-
117-
// Mark that, first error is displayed. TODO Can use a much cleaner solution.
118-
oneErrorDisplayed = true;
96+
var allErrorKeys = Object.keys(ngModelController.$error);
97+
var firstErrorKey = allErrorKeys[0];
98+
99+
// Add bootstrap error class
100+
formGroupElement.addClass("has-error");
101+
102+
var message = resolveMessage($element, firstErrorKey);
103+
104+
// Find if the parent class already have error message container
105+
var errorElement = formGroupElement.findOne("." + errorElementClass);
106+
var iconMarkup = "<i class=\"fa fa-exclamation-triangle fa-fw\"></i>";
107+
108+
// If not, then append an error container
109+
if (errorElement.length === 0) {
110+
var insertAfter = $element;
111+
// Check if the container have any Bootstrap input group then append the error after it
112+
var groupElement = formGroupElement.findOne(".input-group");
113+
if (groupElement.length > 0) {
114+
insertAfter = groupElement;
119115
}
120-
});
116+
117+
var errorMarkup = "<span class=\"" + markupClasses + "\">" + iconMarkup + message + "</span>";
118+
insertAfter.after(errorMarkup);
119+
} else {
120+
// Else change the message.
121+
errorElement.html(iconMarkup + message).removeClass("ng-hide");
122+
}
121123
}
122124

123125
var validators = ["equalTo", "min", "max", "number", "digits", "length"];

src/services/validation.service.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ angular.module("bootstrap.angular.validation").factory("BsValidationService", fu
8686
addValidator: function($scope, $attr, ngModelController, validatorKey) {
8787
ngModelController.$validators[validatorKey] = function (modelValue, viewValue) {
8888
var value = modelValue || viewValue;
89-
return ngModelController.$isEmpty(value) || genericValidators[validatorKey].validator(value, $scope, $attr, ngModelController);
89+
return ngModelController.$isEmpty(value) || genericValidators[validatorKey].validator(value, $scope, $attr);
9090
};
9191
},
9292
checkNgIncludedURL: function(url) {

0 commit comments

Comments
 (0)