| OLD | NEW |
| 1 part of angular.directive; | 1 part of angular.directive; |
| 2 | 2 |
| 3 /** | 3 abstract class NgValidatable { |
| 4 * NgValidator is the class interface for performing validations for an NgModel
instance. | |
| 5 */ | |
| 6 abstract class NgValidator { | |
| 7 /** | |
| 8 * The name of the validator. This name will be used as the key value within t
he | |
| 9 * model.errorStates map and it will also be applied as a CSS class on the ass
ociated | |
| 10 * DOM element. Therefore, as a best practice, please do not include spaces fo
r the validator | |
| 11 * name since it may cause issues with the CSS naming. | |
| 12 */ | |
| 13 String get name; | 4 String get name; |
| 14 bool isValid(modelValue); | 5 bool isValid(value); |
| 15 } | 6 } |
| 16 | 7 |
| 17 /** | 8 /** |
| 18 * Validates the model depending if required or ng-required is present on the el
ement. | 9 * Validates the model depending if required or ng-required is present on the el
ement. |
| 19 */ | 10 */ |
| 20 @Decorator( | 11 @NgDirective( |
| 21 selector: '[ng-model][required]') | 12 selector: '[ng-model][required]') |
| 22 @Decorator( | 13 @NgDirective( |
| 23 selector: '[ng-model][ng-required]', | 14 selector: '[ng-model][ng-required]', |
| 24 map: const {'ng-required': '=>required'}) | 15 map: const {'ng-required': '=>required'}) |
| 25 class NgModelRequiredValidator implements NgValidator { | 16 class NgModelRequiredValidator implements NgValidatable { |
| 17 bool _required = true; |
| 26 | 18 |
| 27 final String name = 'ng-required'; | 19 String get name => 'required'; |
| 28 bool _required = true; | |
| 29 final NgModel _ngModel; | |
| 30 | 20 |
| 31 NgModelRequiredValidator(NgModel this._ngModel) { | 21 NgModelRequiredValidator(NgModel ngModel) { |
| 32 _ngModel.addValidator(this); | 22 ngModel.addValidator(this); |
| 33 } | 23 } |
| 34 | 24 |
| 35 bool isValid(modelValue) { | 25 bool isValid(value) { |
| 36 // Any element which isn't required is always valid. | 26 // Any element which isn't required is always valid. |
| 37 if (!_required) return true; | 27 if (!_required) return true; |
| 38 // Null is not a value, therefore not valid. | 28 // Null is not a value, therefore not valid. |
| 39 if (modelValue == null) return false; | 29 if (value == null) return false; |
| 40 // Empty lists and/or strings are not valid. | 30 // Empty lists and/or strings are not valid. |
| 41 // NOTE: This is an excellent use case for structural typing. | 31 // NOTE: This is an excellent use case for structural typing. |
| 42 // We really want anything object that has a 'isEmpty' property. | 32 // We really want anything object that has a 'isEmpty' property. |
| 43 return !((modelValue is List || modelValue is String) && modelValue.isEmpty)
; | 33 return !((value is List || value is String) && value.isEmpty); |
| 44 } | 34 } |
| 45 | 35 |
| 46 set required(value) { | 36 set required(value) { |
| 47 _required = value == null ? false : value; | 37 _required = value == null ? false : value; |
| 48 _ngModel.validateLater(); | |
| 49 } | 38 } |
| 50 } | 39 } |
| 51 | 40 |
| 52 /** | 41 /** |
| 53 * Validates the model to see if its contents match a valid URL pattern. | 42 * Validates the model to see if its contents match a valid URL pattern. |
| 54 */ | 43 */ |
| 55 @Decorator(selector: 'input[type=url][ng-model]') | 44 @NgDirective(selector: 'input[type=url][ng-model]') |
| 56 class NgModelUrlValidator implements NgValidator { | 45 class NgModelUrlValidator implements NgValidatable { |
| 57 static final URL_REGEXP = new RegExp( | 46 static final URL_REGEXP = new RegExp( |
| 58 r'^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?' + | 47 r'^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?' + |
| 59 r'(\/|\/([\w#!:.?+=&%@!\-\/]))?$'); | 48 r'(\/|\/([\w#!:.?+=&%@!\-\/]))?$'); |
| 60 | 49 |
| 61 final String name = 'ng-url'; | 50 String get name => 'url'; |
| 62 | 51 |
| 63 NgModelUrlValidator(NgModel ngModel) { | 52 NgModelUrlValidator(NgModel ngModel) { |
| 64 ngModel.addValidator(this); | 53 ngModel.addValidator(this); |
| 65 } | 54 } |
| 66 | 55 |
| 67 bool isValid(modelValue) => | 56 bool isValid(value) => |
| 68 modelValue == null || modelValue.isEmpty || URL_REGEXP.hasMatch(modelValue
); | 57 value == null || value.isEmpty || URL_REGEXP.hasMatch(value); |
| 69 } | 58 } |
| 70 | 59 |
| 71 /** | 60 /** |
| 72 * Validates the model to see if its contents match a valid email pattern. | 61 * Validates the model to see if its contents match a valid email pattern. |
| 73 */ | 62 */ |
| 74 @Decorator(selector: 'input[type=email][ng-model]') | 63 @NgDirective(selector: 'input[type=email][ng-model]') |
| 75 class NgModelEmailValidator implements NgValidator { | 64 class NgModelEmailValidator implements NgValidatable { |
| 76 static final EMAIL_REGEXP = new RegExp( | 65 static final EMAIL_REGEXP = new RegExp( |
| 77 r'^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}$'); | 66 r'^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}$'); |
| 78 | 67 |
| 79 final String name = 'ng-email'; | 68 String get name => 'email'; |
| 80 | 69 |
| 81 NgModelEmailValidator(NgModel ngModel) { | 70 NgModelEmailValidator(NgModel ngModel) { |
| 82 ngModel.addValidator(this); | 71 ngModel.addValidator(this); |
| 83 } | 72 } |
| 84 | 73 |
| 85 bool isValid(modelValue) => | 74 bool isValid(value) => |
| 86 modelValue == null || modelValue.isEmpty || EMAIL_REGEXP.hasMatch(modelVal
ue); | 75 value == null || value.isEmpty || EMAIL_REGEXP.hasMatch(value); |
| 87 } | 76 } |
| 88 | 77 |
| 89 /** | 78 /** |
| 90 * Validates the model to see if its contents match a valid number. | 79 * Validates the model to see if its contents match a valid number. |
| 91 */ | 80 */ |
| 92 @Decorator(selector: 'input[type=number][ng-model]') | 81 @NgDirective(selector: 'input[type=number][ng-model]') |
| 93 @Decorator(selector: 'input[type=range][ng-model]') | 82 class NgModelNumberValidator implements NgValidatable { |
| 94 class NgModelNumberValidator implements NgValidator { | 83 String get name => 'number'; |
| 95 | |
| 96 final String name = 'ng-number'; | |
| 97 | 84 |
| 98 NgModelNumberValidator(NgModel ngModel) { | 85 NgModelNumberValidator(NgModel ngModel) { |
| 99 ngModel.addValidator(this); | 86 ngModel.addValidator(this); |
| 100 } | 87 } |
| 101 | 88 |
| 102 bool isValid(modelValue) { | 89 bool isValid(value) { |
| 103 if (modelValue != null) { | 90 if (value != null) { |
| 104 try { | 91 try { |
| 105 num val = double.parse(modelValue.toString()); | 92 num val = double.parse(value.toString()); |
| 106 if (val.isNaN) { | |
| 107 return false; | |
| 108 } | |
| 109 } catch(exception, stackTrace) { | 93 } catch(exception, stackTrace) { |
| 110 return false; | 94 return false; |
| 111 } | 95 } |
| 112 } | 96 } |
| 113 return true; | 97 return true; |
| 114 } | 98 } |
| 115 } | 99 } |
| 116 | 100 |
| 117 /** | 101 /** |
| 118 * Validates the model to see if the numeric value than or equal to the max valu
e. | |
| 119 */ | |
| 120 @Decorator(selector: 'input[type=number][ng-model][max]') | |
| 121 @Decorator(selector: 'input[type=range][ng-model][max]') | |
| 122 @Decorator( | |
| 123 selector: 'input[type=number][ng-model][ng-max]', | |
| 124 map: const {'ng-max': '=>max'}) | |
| 125 @Decorator( | |
| 126 selector: 'input[type=range][ng-model][ng-max]', | |
| 127 map: const {'ng-max': '=>max'}) | |
| 128 class NgModelMaxNumberValidator implements NgValidator { | |
| 129 | |
| 130 final String name = 'ng-max'; | |
| 131 double _max; | |
| 132 final NgModel _ngModel; | |
| 133 | |
| 134 NgModelMaxNumberValidator(NgModel this._ngModel) { | |
| 135 _ngModel.addValidator(this); | |
| 136 } | |
| 137 | |
| 138 @NgAttr('max') | |
| 139 get max => _max; | |
| 140 set max(value) { | |
| 141 try { | |
| 142 num parsedValue = double.parse(value); | |
| 143 _max = parsedValue.isNaN ? _max : parsedValue; | |
| 144 } catch(e) { | |
| 145 _max = null; | |
| 146 } finally { | |
| 147 _ngModel.validateLater(); | |
| 148 } | |
| 149 } | |
| 150 | |
| 151 bool isValid(modelValue) { | |
| 152 if (modelValue == null || max == null) return true; | |
| 153 | |
| 154 try { | |
| 155 num parsedValue = double.parse(modelValue.toString()); | |
| 156 if (!parsedValue.isNaN) { | |
| 157 return parsedValue <= max; | |
| 158 } | |
| 159 } catch(exception, stackTrace) {} | |
| 160 | |
| 161 //this validator doesn't care if the type conversation fails or the value | |
| 162 //is not a number (NaN) because NgModelNumberValidator will handle the | |
| 163 //number-based validation either way. | |
| 164 return true; | |
| 165 } | |
| 166 } | |
| 167 | |
| 168 /** | |
| 169 * Validates the model to see if the numeric value is greater than or equal to t
he min value. | |
| 170 */ | |
| 171 @Decorator(selector: 'input[type=number][ng-model][min]') | |
| 172 @Decorator(selector: 'input[type=range][ng-model][min]') | |
| 173 @Decorator( | |
| 174 selector: 'input[type=number][ng-model][ng-min]', | |
| 175 map: const {'ng-min': '=>min'}) | |
| 176 @Decorator( | |
| 177 selector: 'input[type=range][ng-model][ng-min]', | |
| 178 map: const {'ng-min': '=>min'}) | |
| 179 class NgModelMinNumberValidator implements NgValidator { | |
| 180 | |
| 181 final String name = 'ng-min'; | |
| 182 double _min; | |
| 183 final NgModel _ngModel; | |
| 184 | |
| 185 NgModelMinNumberValidator(NgModel this._ngModel) { | |
| 186 _ngModel.addValidator(this); | |
| 187 } | |
| 188 | |
| 189 @NgAttr('min') | |
| 190 get min => _min; | |
| 191 set min(value) { | |
| 192 try { | |
| 193 num parsedValue = double.parse(value); | |
| 194 _min = parsedValue.isNaN ? _min : parsedValue; | |
| 195 } catch(e) { | |
| 196 _min = null; | |
| 197 } finally { | |
| 198 _ngModel.validateLater(); | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 bool isValid(modelValue) { | |
| 203 if (modelValue == null || min == null) return true; | |
| 204 | |
| 205 try { | |
| 206 num parsedValue = double.parse(modelValue.toString()); | |
| 207 if (!parsedValue.isNaN) { | |
| 208 return parsedValue >= min; | |
| 209 } | |
| 210 } catch(exception, stackTrace) {} | |
| 211 | |
| 212 //this validator doesn't care if the type conversation fails or the value | |
| 213 //is not a number (NaN) because NgModelNumberValidator will handle the | |
| 214 //number-based validation either way. | |
| 215 return true; | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 /** | |
| 220 * Validates the model to see if its contents match the given pattern present on
either the | 102 * Validates the model to see if its contents match the given pattern present on
either the |
| 221 * HTML pattern or ng-pattern attributes present on the input element. | 103 * HTML pattern or ng-pattern attributes present on the input element. |
| 222 */ | 104 */ |
| 223 @Decorator(selector: '[ng-model][pattern]') | 105 @NgDirective(selector: '[ng-model][pattern]') |
| 224 @Decorator( | 106 @NgDirective( |
| 225 selector: '[ng-model][ng-pattern]', | 107 selector: '[ng-model][ng-pattern]', |
| 226 map: const {'ng-pattern': '=>pattern'}) | 108 map: const {'ng-pattern': '=>pattern'}) |
| 227 class NgModelPatternValidator implements NgValidator { | 109 class NgModelPatternValidator implements NgValidatable { |
| 110 RegExp _pattern; |
| 228 | 111 |
| 229 final String name = 'ng-pattern'; | 112 String get name => 'pattern'; |
| 230 RegExp _pattern; | |
| 231 final NgModel _ngModel; | |
| 232 | 113 |
| 233 NgModelPatternValidator(NgModel this._ngModel) { | 114 NgModelPatternValidator(NgModel ngModel) { |
| 234 _ngModel.addValidator(this); | 115 ngModel.addValidator(this); |
| 235 } | 116 } |
| 236 | 117 |
| 237 bool isValid(modelValue) { | 118 bool isValid(value) { |
| 238 //remember, only required validates for the input being empty | 119 //remember, only required validates for the input being empty |
| 239 return _pattern == null || modelValue == null || modelValue.length == 0 || | 120 return _pattern == null || value == null || value.length == 0 || |
| 240 _pattern.hasMatch(modelValue); | 121 _pattern.hasMatch(value); |
| 241 } | 122 } |
| 242 | 123 |
| 243 @NgAttr('pattern') | 124 @NgAttr('pattern') |
| 244 void set pattern(val) { | 125 set pattern(val) => |
| 245 _pattern = val != null && val.length > 0 ? new RegExp(val) : null; | 126 _pattern = val != null && val.length > 0 ? new RegExp(val) : null; |
| 246 _ngModel.validateLater(); | |
| 247 } | |
| 248 } | 127 } |
| 249 | 128 |
| 250 /** | 129 /** |
| 251 * Validates the model to see if the length of its contents are greater than or | 130 * Validates the model to see if the length of its contents are greater than or |
| 252 * equal to the minimum length set in place by the HTML minlength or | 131 * equal to the minimum length set in place by the HTML minlength or |
| 253 * ng-minlength attributes present on the input element. | 132 * ng-minlength attributes present on the input element. |
| 254 */ | 133 */ |
| 255 @Decorator(selector: '[ng-model][minlength]') | 134 @NgDirective(selector: '[ng-model][minlength]') |
| 256 @Decorator( | 135 @NgDirective( |
| 257 selector: '[ng-model][ng-minlength]', | 136 selector: '[ng-model][ng-minlength]', |
| 258 map: const {'ng-minlength': '=>minlength'}) | 137 map: const {'ng-minlength': '=>minlength'}) |
| 259 class NgModelMinLengthValidator implements NgValidator { | 138 class NgModelMinLengthValidator implements NgValidatable { |
| 139 int _minlength; |
| 260 | 140 |
| 261 final String name = 'ng-minlength'; | 141 String get name => 'minlength'; |
| 262 int _minlength; | |
| 263 final NgModel _ngModel; | |
| 264 | 142 |
| 265 NgModelMinLengthValidator(NgModel this._ngModel) { | 143 NgModelMinLengthValidator(NgModel ngModel) { |
| 266 _ngModel.addValidator(this); | 144 ngModel.addValidator(this); |
| 267 } | 145 } |
| 268 | 146 |
| 269 bool isValid(modelValue) { | 147 bool isValid(value) { |
| 270 //remember, only required validates for the input being empty | 148 //remember, only required validates for the input being empty |
| 271 return _minlength == 0 || modelValue == null || modelValue.length == 0 || | 149 return _minlength == 0 || value == null || value.length == 0 || |
| 272 modelValue.length >= _minlength; | 150 value.length >= _minlength; |
| 273 } | 151 } |
| 274 | 152 |
| 275 @NgAttr('minlength') | 153 @NgAttr('minlength') |
| 276 void set minlength(value) { | 154 set minlength(value) => |
| 277 _minlength = value == null ? 0 : int.parse(value.toString()); | 155 _minlength = value == null ? 0 : int.parse(value.toString()); |
| 278 _ngModel.validateLater(); | |
| 279 } | |
| 280 } | 156 } |
| 281 | 157 |
| 282 /** | 158 /** |
| 283 * Validates the model to see if the length of its contents are less than or | 159 * Validates the model to see if the length of its contents are less than or |
| 284 * equal to the maximum length set in place by the HTML maxlength or | 160 * equal to the maximum length set in place by the HTML maxlength or |
| 285 * ng-maxlength attributes present on the input element. | 161 * ng-maxlength attributes present on the input element. |
| 286 */ | 162 */ |
| 287 @Decorator(selector: '[ng-model][maxlength]') | 163 @NgDirective(selector: '[ng-model][maxlength]') |
| 288 @Decorator( | 164 @NgDirective( |
| 289 selector: '[ng-model][ng-maxlength]', | 165 selector: '[ng-model][ng-maxlength]', |
| 290 map: const {'ng-maxlength': '=>maxlength'}) | 166 map: const {'ng-maxlength': '=>maxlength'}) |
| 291 class NgModelMaxLengthValidator implements NgValidator { | 167 class NgModelMaxLengthValidator implements NgValidatable { |
| 168 int _maxlength = 0; |
| 292 | 169 |
| 293 final String name = 'ng-maxlength'; | 170 String get name => 'maxlength'; |
| 294 int _maxlength = 0; | |
| 295 final NgModel _ngModel; | |
| 296 | 171 |
| 297 NgModelMaxLengthValidator(NgModel this._ngModel) { | 172 NgModelMaxLengthValidator(NgModel ngModel) { |
| 298 _ngModel.addValidator(this); | 173 ngModel.addValidator(this); |
| 299 } | 174 } |
| 300 | 175 |
| 301 bool isValid(modelValue) => | 176 bool isValid(value) => |
| 302 _maxlength == 0 || (modelValue == null ? 0 : modelValue.length) <= _maxlen
gth; | 177 _maxlength == 0 || (value == null ? 0 : value.length) <= _maxlength; |
| 303 | 178 |
| 304 @NgAttr('maxlength') | 179 @NgAttr('maxlength') |
| 305 void set maxlength(value) { | 180 set maxlength(value) => |
| 306 _maxlength = value == null ? 0 : int.parse(value.toString()); | 181 _maxlength = value == null ? 0 : int.parse(value.toString()); |
| 307 _ngModel.validateLater(); | |
| 308 } | |
| 309 } | 182 } |
| OLD | NEW |