@@ -12,29 +12,42 @@ angular.module('bootstrap.angular.validation').factory('BsValidationService', ['
12
12
var customFormGroup = '[bs-form-group]' ;
13
13
var formGroupClass = '.form-group' ;
14
14
15
- var genericValidators = {
16
- digits : function ( value ) {
15
+ var _genericValidators = [ {
16
+ name : 'digits' ,
17
+ validateFn : function ( value ) {
17
18
return ( / ^ \d + $ / ) . test ( value ) ;
18
- } ,
19
- equalto : function ( value , $scope , attr ) {
19
+ }
20
+ } , {
21
+ name : 'equalto' ,
22
+ validateFn : function ( value , $scope , attr ) {
20
23
return value + '' === $scope . $eval ( attr . equalto ) + '' ;
21
- } ,
22
- number : function ( value ) {
24
+ }
25
+ } , {
26
+ name : 'number' ,
27
+ validateFn : function ( value ) {
23
28
return ( / ^ - ? (?: \d + | \d { 1 , 3 } (?: , \d { 3 } ) + ) ? (?: \. \d + ) ? $ / ) . test ( value ) ;
24
- } ,
25
- min : function ( value , $scope , attr ) {
29
+ }
30
+ } , {
31
+ name : 'min' ,
32
+ validateFn : function ( value , $scope , attr ) {
26
33
return parseFloat ( value ) >= parseFloat ( attr . min ) ;
27
- } ,
28
- max : function ( value , $scope , attr ) {
34
+ }
35
+ } , {
36
+ name : 'max' ,
37
+ validateFn : function ( value , $scope , attr ) {
29
38
return parseFloat ( value ) <= parseFloat ( attr . max ) ;
30
- } ,
31
- length : function ( value , $scope , attr ) {
39
+ }
40
+ } , {
41
+ name : 'length' ,
42
+ validateFn : function ( value , $scope , attr ) {
32
43
return value . length === parseInt ( attr . length ) ;
33
- } ,
34
- strictemail : function ( value ) {
44
+ }
45
+ } , {
46
+ name : 'strictemail' ,
47
+ validateFn : function ( value ) {
35
48
return new RegExp ( / ^ [ _ a - z 0 - 9 ] + ( \. [ _ a - z 0 - 9 ] + ) * @ [ a - z 0 - 9 - ] + ( \. [ a - z 0 - 9 - ] + ) * ( \. [ a - z ] { 2 , 4 } ) $ / ) . test ( value ) ;
36
49
}
37
- } ;
50
+ } ] ;
38
51
39
52
function getTrigger ( $element , triggerEvent ) {
40
53
var attributeName = 'bs-trigger' ;
@@ -51,17 +64,17 @@ angular.module('bootstrap.angular.validation').factory('BsValidationService', ['
51
64
return validationConfig . shouldValidateOn ( triggerEvent ) ;
52
65
}
53
66
67
+ function removeClassByPrefix ( element , prefix ) {
68
+ var regx = new RegExp ( '\\b' + prefix + '.*\\b' , 'g' ) ;
69
+ element [ 0 ] . className = element [ 0 ] . className . replace ( regx , '' ) . replace ( / \s \s + / g, ' ' ) ;
70
+ return element ;
71
+ }
72
+
54
73
var meta = [ 'matchName' ] ;
55
74
56
75
return {
57
- /**
58
- * Search all the input element inside the given DOM element and apply the 'bs-validation' directive so we
59
- * need not a add it for every form element.
60
- */
61
76
getValidators : function ( ) {
62
- var builtIn = [ 'equalto' , 'min' , 'max' , 'number' , 'digits' , 'length' ] ;
63
- var additional = Object . keys ( genericValidators ) ;
64
- return builtIn . concat ( additional ) ;
77
+ return _genericValidators ;
65
78
} ,
66
79
67
80
getMetaInformation : function ( $element ) {
@@ -87,13 +100,32 @@ angular.module('bootstrap.angular.validation').factory('BsValidationService', ['
87
100
}
88
101
} ,
89
102
90
- addValidator : function ( $scope , $attr , ngModelController , validatorKey ) {
91
- ngModelController . $validators [ validatorKey ] = function ( modelValue , viewValue ) {
103
+ addValidator : function ( $scope , $element , $ attr, ngModelController , validator ) {
104
+ ngModelController . $validators [ validator . name ] = function ( modelValue , viewValue ) {
92
105
var value = modelValue || viewValue ;
93
- return ngModelController . $isEmpty ( value ) || genericValidators [ validatorKey ] ( value , $scope , $attr ) ;
106
+ if ( ngModelController . $isEmpty ( value ) ) {
107
+ return true ;
108
+ }
109
+
110
+ // See https://github.com/sagrawal14/angular-extras/blob/v0.1.3/src/extras/array.js#L91 for "find" function
111
+ return validator . validateFn ( value , $scope , $attr ) ;
94
112
} ;
95
113
} ,
96
114
115
+ /**
116
+ * Add a custom validator to the list of generic validators.
117
+ * @param genericValidationObject for example, to a add a generic validator to accept either "foo" or "bar":
118
+ * {
119
+ * name: 'foobar',
120
+ * validateFn: function(value, $scope, attr) {
121
+ * return value === 'foo' || value === 'bar';
122
+ * }
123
+ * }
124
+ */
125
+ addGenericValidator : function ( genericValidationObject ) {
126
+ _genericValidators . push ( genericValidationObject ) ;
127
+ } ,
128
+
97
129
displayErrorPreference : function ( $element , $attr ) {
98
130
var attrName = displayErrorAsAttrName ;
99
131
if ( $attr [ attrName ] ) {
@@ -204,6 +236,21 @@ angular.module('bootstrap.angular.validation').factory('BsValidationService', ['
204
236
205
237
shouldValidateOnSubmit : function ( $element ) {
206
238
return getTrigger ( $element , 'submit' ) ;
239
+ } ,
240
+
241
+ /**
242
+ * Add or remove various classes on form-group element. For example, if an input has two errors "required" & "min"
243
+ * then whenever the validation fails, form-group element will have classes like "bs-has-error-required" or
244
+ * "bs-has-error-min".
245
+ * @param $formGroupElement jQLite/jQuery form-group element
246
+ * @param errors Errors object as returned by ngModelController.$error
247
+ */
248
+ toggleErrorKeyClasses : function ( $formGroupElement , errors ) {
249
+ removeClassByPrefix ( $formGroupElement , 'bs-has-error-' ) ;
250
+
251
+ angular . forEach ( errors , function ( value , key ) {
252
+ $formGroupElement . addClass ( 'bs-has-error-' + key ) ;
253
+ } ) ;
207
254
}
208
255
209
256
} ;
0 commit comments