@@ -384,11 +384,6 @@ var inputType = {
384
384
} ;
385
385
386
386
387
- function isEmpty ( value ) {
388
- return isUndefined ( value ) || value === '' || value === null || value !== value ;
389
- }
390
-
391
-
392
387
function textInputType ( scope , element , attr , ctrl , $sniffer , $browser ) {
393
388
394
389
var listener = function ( ) {
@@ -445,7 +440,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
445
440
446
441
447
442
ctrl . $render = function ( ) {
448
- element . val ( isEmpty ( ctrl . $viewValue ) ? '' : ctrl . $viewValue ) ;
443
+ element . val ( ctrl . $ isEmpty( ctrl . $viewValue ) ? '' : ctrl . $viewValue ) ;
449
444
} ;
450
445
451
446
// pattern validator
@@ -454,7 +449,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
454
449
match ;
455
450
456
451
var validate = function ( regexp , value ) {
457
- if ( isEmpty ( value ) || regexp . test ( value ) ) {
452
+ if ( ctrl . $ isEmpty( value ) || regexp . test ( value ) ) {
458
453
ctrl . $setValidity ( 'pattern' , true ) ;
459
454
return value ;
460
455
} else {
@@ -468,7 +463,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
468
463
if ( match ) {
469
464
pattern = new RegExp ( match [ 1 ] , match [ 2 ] ) ;
470
465
patternValidator = function ( value ) {
471
- return validate ( pattern , value )
466
+ return validate ( pattern , value ) ;
472
467
} ;
473
468
} else {
474
469
patternValidator = function ( value ) {
@@ -491,7 +486,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
491
486
if ( attr . ngMinlength ) {
492
487
var minlength = int ( attr . ngMinlength ) ;
493
488
var minLengthValidator = function ( value ) {
494
- if ( ! isEmpty ( value ) && value . length < minlength ) {
489
+ if ( ! ctrl . $ isEmpty( value ) && value . length < minlength ) {
495
490
ctrl . $setValidity ( 'minlength' , false ) ;
496
491
return undefined ;
497
492
} else {
@@ -508,7 +503,7 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
508
503
if ( attr . ngMaxlength ) {
509
504
var maxlength = int ( attr . ngMaxlength ) ;
510
505
var maxLengthValidator = function ( value ) {
511
- if ( ! isEmpty ( value ) && value . length > maxlength ) {
506
+ if ( ! ctrl . $ isEmpty( value ) && value . length > maxlength ) {
512
507
ctrl . $setValidity ( 'maxlength' , false ) ;
513
508
return undefined ;
514
509
} else {
@@ -526,7 +521,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
526
521
textInputType ( scope , element , attr , ctrl , $sniffer , $browser ) ;
527
522
528
523
ctrl . $parsers . push ( function ( value ) {
529
- var empty = isEmpty ( value ) ;
524
+ var empty = ctrl . $ isEmpty( value ) ;
530
525
if ( empty || NUMBER_REGEXP . test ( value ) ) {
531
526
ctrl . $setValidity ( 'number' , true ) ;
532
527
return value === '' ? null : ( empty ? value : parseFloat ( value ) ) ;
@@ -537,13 +532,13 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
537
532
} ) ;
538
533
539
534
ctrl . $formatters . push ( function ( value ) {
540
- return isEmpty ( value ) ? '' : '' + value ;
535
+ return ctrl . $ isEmpty( value ) ? '' : '' + value ;
541
536
} ) ;
542
537
543
538
if ( attr . min ) {
544
539
var min = parseFloat ( attr . min ) ;
545
540
var minValidator = function ( value ) {
546
- if ( ! isEmpty ( value ) && value < min ) {
541
+ if ( ! ctrl . $ isEmpty( value ) && value < min ) {
547
542
ctrl . $setValidity ( 'min' , false ) ;
548
543
return undefined ;
549
544
} else {
@@ -559,7 +554,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
559
554
if ( attr . max ) {
560
555
var max = parseFloat ( attr . max ) ;
561
556
var maxValidator = function ( value ) {
562
- if ( ! isEmpty ( value ) && value > max ) {
557
+ if ( ! ctrl . $ isEmpty( value ) && value > max ) {
563
558
ctrl . $setValidity ( 'max' , false ) ;
564
559
return undefined ;
565
560
} else {
@@ -574,7 +569,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
574
569
575
570
ctrl . $formatters . push ( function ( value ) {
576
571
577
- if ( isEmpty ( value ) || isNumber ( value ) ) {
572
+ if ( ctrl . $ isEmpty( value ) || isNumber ( value ) ) {
578
573
ctrl . $setValidity ( 'number' , true ) ;
579
574
return value ;
580
575
} else {
@@ -588,7 +583,7 @@ function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
588
583
textInputType ( scope , element , attr , ctrl , $sniffer , $browser ) ;
589
584
590
585
var urlValidator = function ( value ) {
591
- if ( isEmpty ( value ) || URL_REGEXP . test ( value ) ) {
586
+ if ( ctrl . $ isEmpty( value ) || URL_REGEXP . test ( value ) ) {
592
587
ctrl . $setValidity ( 'url' , true ) ;
593
588
return value ;
594
589
} else {
@@ -605,7 +600,7 @@ function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
605
600
textInputType ( scope , element , attr , ctrl , $sniffer , $browser ) ;
606
601
607
602
var emailValidator = function ( value ) {
608
- if ( isEmpty ( value ) || EMAIL_REGEXP . test ( value ) ) {
603
+ if ( ctrl . $ isEmpty( value ) || EMAIL_REGEXP . test ( value ) ) {
609
604
ctrl . $setValidity ( 'email' , true ) ;
610
605
return value ;
611
606
} else {
@@ -657,6 +652,11 @@ function checkboxInputType(scope, element, attr, ctrl) {
657
652
element [ 0 ] . checked = ctrl . $viewValue ;
658
653
} ;
659
654
655
+ // Override the standard `$isEmpty` because a value of `false` means empty in a checkbox.
656
+ ctrl . $isEmpty = function ( value ) {
657
+ return value !== trueValue ;
658
+ } ;
659
+
660
660
ctrl . $formatters . push ( function ( value ) {
661
661
return value === trueValue ;
662
662
} ) ;
@@ -992,6 +992,25 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
992
992
*/
993
993
this . $render = noop ;
994
994
995
+ /**
996
+ * @ngdoc function
997
+ * @name { ng.directive:ngModel.NgModelController#$isEmpty
998
+ * @methodOf ng.directive:ngModel.NgModelController
999
+ *
1000
+ * @description
1001
+ * This is called when we need to determine if the value of the input is empty.
1002
+ *
1003
+ * For instance, the required directive does this to work out if the input has data or not.
1004
+ * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.
1005
+ *
1006
+ * You can override this for input directives whose concept of being empty is different to the
1007
+ * default. The `checkboxInputType` directive does this because in its case a value of `false`
1008
+ * implies empty.
1009
+ */
1010
+ this . $isEmpty = function ( value ) {
1011
+ return isUndefined ( value ) || value === '' || value === null || value !== value ;
1012
+ } ;
1013
+
995
1014
var parentForm = $element . inheritedData ( '$formController' ) || nullFormCtrl ,
996
1015
invalidCount = 0 , // used to easily determine if we are valid
997
1016
$error = this . $error = { } ; // keep invalid keys here
@@ -1266,7 +1285,7 @@ var requiredDirective = function() {
1266
1285
attr . required = true ; // force truthy in case we are on non input element
1267
1286
1268
1287
var validator = function ( value ) {
1269
- if ( attr . required && ( isEmpty ( value ) || value === false ) ) {
1288
+ if ( attr . required && ctrl . $ isEmpty( value ) ) {
1270
1289
ctrl . $setValidity ( 'required' , false ) ;
1271
1290
return ;
1272
1291
} else {
@@ -1327,7 +1346,7 @@ var requiredDirective = function() {
1327
1346
1328
1347
it('should be invalid if empty', function() {
1329
1348
input('names').enter('');
1330
- expect(binding('names')).toEqual('[] ');
1349
+ expect(binding('names')).toEqual('');
1331
1350
expect(binding('myForm.namesInput.$valid')).toEqual('false');
1332
1351
expect(element('span.error').css('display')).not().toBe('none');
1333
1352
});
@@ -1342,6 +1361,9 @@ var ngListDirective = function() {
1342
1361
separator = match && new RegExp ( match [ 1 ] ) || attr . ngList || ',' ;
1343
1362
1344
1363
var parse = function ( viewValue ) {
1364
+ // If the viewValue is invalid (say required but empty) it will be `undefined`
1365
+ if ( isUndefined ( viewValue ) ) return ;
1366
+
1345
1367
var list = [ ] ;
1346
1368
1347
1369
if ( viewValue ) {
@@ -1361,6 +1383,11 @@ var ngListDirective = function() {
1361
1383
1362
1384
return undefined ;
1363
1385
} ) ;
1386
+
1387
+ // Override the standard $isEmpty because an empty array means the input is empty.
1388
+ ctrl . $isEmpty = function ( value ) {
1389
+ return ! value || ! value . length ;
1390
+ } ;
1364
1391
}
1365
1392
} ;
1366
1393
} ;
0 commit comments