@@ -1435,6 +1435,12 @@ var VALID_CLASS = 'ng-valid',
1435
1435
* ngModel.$formatters.push(formatter);
1436
1436
* ```
1437
1437
*
1438
+ * @property {Object.<string, function> } $validators A collection of validators that are applied
1439
+ * whenever the model value changes. The key value within the object refers to the name of the
1440
+ * validator while the function refers to the validation operation. The validation operation is
1441
+ * provided with the model value as an argument and must return a true or false value depending
1442
+ * on the response of that validation.
1443
+ *
1438
1444
* @property {Array.<Function> } $viewChangeListeners Array of functions to execute whenever the
1439
1445
* view value has changed. It is called with no arguments, and its return value is ignored.
1440
1446
* This can be used in place of additional $watches against the model value.
@@ -1551,6 +1557,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1551
1557
function ( $scope , $exceptionHandler , $attr , $element , $parse , $animate , $timeout ) {
1552
1558
this . $viewValue = Number . NaN ;
1553
1559
this . $modelValue = Number . NaN ;
1560
+ this . $validators = { } ;
1554
1561
this . $parsers = [ ] ;
1555
1562
this . $formatters = [ ] ;
1556
1563
this . $viewChangeListeners = [ ] ;
@@ -1626,7 +1633,8 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1626
1633
* Change the validity state, and notifies the form when the control changes validity. (i.e. it
1627
1634
* does not notify form if given validator is already marked as invalid).
1628
1635
*
1629
- * This method should be called by validators - i.e. the parser or formatter functions.
1636
+ * This method can be called within $parsers/$formatters. However, if possible, please use the
1637
+ * `ngModel.$validators` pipeline which is designed to handle validations with true/false values.
1630
1638
*
1631
1639
* @param {string } validationErrorKey Name of the validator. the `validationErrorKey` will assign
1632
1640
* to `$error[validationErrorKey]=isValid` so that it is available for data-binding.
@@ -1743,6 +1751,23 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1743
1751
ctrl . $render ( ) ;
1744
1752
} ;
1745
1753
1754
+ /**
1755
+ * @ngdoc method
1756
+ * @name ngModel.NgModelController#$validate
1757
+ *
1758
+ * @description
1759
+ * Runs each of the registered validations set on the $validators object.
1760
+ */
1761
+ this . $validate = function ( ) {
1762
+ this . $$runValidators ( ctrl . $modelValue , ctrl . $viewValue ) ;
1763
+ } ;
1764
+
1765
+ this . $$runValidators = function ( modelValue , viewValue ) {
1766
+ forEach ( ctrl . $validators , function ( fn , name ) {
1767
+ ctrl . $setValidity ( name , fn ( modelValue , viewValue ) ) ;
1768
+ } ) ;
1769
+ } ;
1770
+
1746
1771
/**
1747
1772
* @ngdoc method
1748
1773
* @name ngModel.NgModelController#$commitViewValue
@@ -1755,12 +1780,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1755
1780
* usually handles calling this in response to input events.
1756
1781
*/
1757
1782
this . $commitViewValue = function ( ) {
1758
- var value = ctrl . $viewValue ;
1783
+ var viewValue = ctrl . $viewValue ;
1759
1784
$timeout . cancel ( pendingDebounce ) ;
1760
- if ( ctrl . $$lastCommittedViewValue === value ) {
1785
+ if ( ctrl . $$lastCommittedViewValue === viewValue ) {
1761
1786
return ;
1762
1787
}
1763
- ctrl . $$lastCommittedViewValue = value ;
1788
+ ctrl . $$lastCommittedViewValue = viewValue ;
1764
1789
1765
1790
// change to dirty
1766
1791
if ( ctrl . $pristine ) {
@@ -1771,13 +1796,19 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1771
1796
parentForm . $setDirty ( ) ;
1772
1797
}
1773
1798
1799
+ var modelValue = viewValue ;
1774
1800
forEach ( ctrl . $parsers , function ( fn ) {
1775
- value = fn ( value ) ;
1801
+ modelValue = fn ( modelValue ) ;
1776
1802
} ) ;
1777
1803
1778
- if ( ctrl . $modelValue !== value ) {
1779
- ctrl . $modelValue = value ;
1780
- ngModelSet ( $scope , value ) ;
1804
+ if ( ctrl . $modelValue !== modelValue &&
1805
+ ( isUndefined ( ctrl . $$invalidModelValue ) || ctrl . $$invalidModelValue != modelValue ) ) {
1806
+
1807
+ ctrl . $$runValidators ( modelValue , viewValue ) ;
1808
+ ctrl . $modelValue = ctrl . $valid ? modelValue : undefined ;
1809
+ ctrl . $$invalidModelValue = ctrl . $valid ? undefined : modelValue ;
1810
+
1811
+ ngModelSet ( $scope , ctrl . $modelValue ) ;
1781
1812
forEach ( ctrl . $viewChangeListeners , function ( listener ) {
1782
1813
try {
1783
1814
listener ( ) ;
@@ -1851,26 +1882,31 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1851
1882
1852
1883
// model -> value
1853
1884
$scope . $watch ( function ngModelWatch ( ) {
1854
- var value = ngModelGet ( $scope ) ;
1885
+ var modelValue = ngModelGet ( $scope ) ;
1855
1886
1856
1887
// if scope model value and ngModel value are out of sync
1857
- if ( ctrl . $modelValue !== value ) {
1888
+ if ( ctrl . $modelValue !== modelValue &&
1889
+ ( isUndefined ( ctrl . $$invalidModelValue ) || ctrl . $$invalidModelValue != modelValue ) ) {
1858
1890
1859
1891
var formatters = ctrl . $formatters ,
1860
1892
idx = formatters . length ;
1861
1893
1862
- ctrl . $modelValue = value ;
1894
+ var viewValue = modelValue ;
1863
1895
while ( idx -- ) {
1864
- value = formatters [ idx ] ( value ) ;
1896
+ viewValue = formatters [ idx ] ( viewValue ) ;
1865
1897
}
1866
1898
1867
- if ( ctrl . $viewValue !== value ) {
1868
- ctrl . $viewValue = ctrl . $$lastCommittedViewValue = value ;
1899
+ ctrl . $$runValidators ( modelValue , viewValue ) ;
1900
+ ctrl . $modelValue = ctrl . $valid ? modelValue : undefined ;
1901
+ ctrl . $$invalidModelValue = ctrl . $valid ? undefined : modelValue ;
1902
+
1903
+ if ( ctrl . $viewValue !== viewValue ) {
1904
+ ctrl . $viewValue = ctrl . $$lastCommittedViewValue = viewValue ;
1869
1905
ctrl . $render ( ) ;
1870
1906
}
1871
1907
}
1872
1908
1873
- return value ;
1909
+ return modelValue ;
1874
1910
} ) ;
1875
1911
} ] ;
1876
1912
0 commit comments