@@ -1440,6 +1440,12 @@ var VALID_CLASS = 'ng-valid',
1440
1440
* ngModel.$formatters.push(formatter);
1441
1441
* ```
1442
1442
*
1443
+ * @property {Object.<string, function> } $validators A collection of validators that are applied
1444
+ * whenever the model value changes. The key value within the object refers to the name of the
1445
+ * validator while the function refers to the validation operation. The validation operation is
1446
+ * provided with the model value as an argument and must return a true or false value depending
1447
+ * on the response of that validation.
1448
+ *
1443
1449
* @property {Array.<Function> } $viewChangeListeners Array of functions to execute whenever the
1444
1450
* view value has changed. It is called with no arguments, and its return value is ignored.
1445
1451
* This can be used in place of additional $watches against the model value.
@@ -1558,6 +1564,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1558
1564
function ( $scope , $exceptionHandler , $attr , $element , $parse , $animate , $timeout ) {
1559
1565
this . $viewValue = Number . NaN ;
1560
1566
this . $modelValue = Number . NaN ;
1567
+ this . $validators = { } ;
1561
1568
this . $parsers = [ ] ;
1562
1569
this . $formatters = [ ] ;
1563
1570
this . $viewChangeListeners = [ ] ;
@@ -1637,7 +1644,8 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1637
1644
* Change the validity state, and notifies the form when the control changes validity. (i.e. it
1638
1645
* does not notify form if given validator is already marked as invalid).
1639
1646
*
1640
- * This method should be called by validators - i.e. the parser or formatter functions.
1647
+ * This method can be called within $parsers/$formatters. However, if possible, please use the
1648
+ * `ngModel.$validators` pipeline which is designed to handle validations with true/false values.
1641
1649
*
1642
1650
* @param {string } validationErrorKey Name of the validator. the `validationErrorKey` will assign
1643
1651
* to `$error[validationErrorKey]=isValid` so that it is available for data-binding.
@@ -1786,6 +1794,23 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1786
1794
ctrl . $render ( ) ;
1787
1795
} ;
1788
1796
1797
+ /**
1798
+ * @ngdoc method
1799
+ * @name ngModel.NgModelController#$validate
1800
+ *
1801
+ * @description
1802
+ * Runs each of the registered validations set on the $validators object.
1803
+ */
1804
+ this . $validate = function ( ) {
1805
+ this . $$runValidators ( ctrl . $modelValue , ctrl . $viewValue ) ;
1806
+ } ;
1807
+
1808
+ this . $$runValidators = function ( modelValue , viewValue ) {
1809
+ forEach ( ctrl . $validators , function ( fn , name ) {
1810
+ ctrl . $setValidity ( name , fn ( modelValue , viewValue ) ) ;
1811
+ } ) ;
1812
+ } ;
1813
+
1789
1814
/**
1790
1815
* @ngdoc method
1791
1816
* @name ngModel.NgModelController#$commitViewValue
@@ -1798,12 +1823,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1798
1823
* usually handles calling this in response to input events.
1799
1824
*/
1800
1825
this . $commitViewValue = function ( ) {
1801
- var value = ctrl . $viewValue ;
1826
+ var viewValue = ctrl . $viewValue ;
1802
1827
$timeout . cancel ( pendingDebounce ) ;
1803
- if ( ctrl . $$lastCommittedViewValue === value ) {
1828
+ if ( ctrl . $$lastCommittedViewValue === viewValue ) {
1804
1829
return ;
1805
1830
}
1806
- ctrl . $$lastCommittedViewValue = value ;
1831
+ ctrl . $$lastCommittedViewValue = viewValue ;
1807
1832
1808
1833
// change to dirty
1809
1834
if ( ctrl . $pristine ) {
@@ -1814,13 +1839,19 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1814
1839
parentForm . $setDirty ( ) ;
1815
1840
}
1816
1841
1842
+ var modelValue = viewValue ;
1817
1843
forEach ( ctrl . $parsers , function ( fn ) {
1818
- value = fn ( value ) ;
1844
+ modelValue = fn ( modelValue ) ;
1819
1845
} ) ;
1820
1846
1821
- if ( ctrl . $modelValue !== value ) {
1822
- ctrl . $modelValue = value ;
1823
- ngModelSet ( $scope , value ) ;
1847
+ if ( ctrl . $modelValue !== modelValue &&
1848
+ ( isUndefined ( ctrl . $$invalidModelValue ) || ctrl . $$invalidModelValue != modelValue ) ) {
1849
+
1850
+ ctrl . $$runValidators ( modelValue , viewValue ) ;
1851
+ ctrl . $modelValue = ctrl . $valid ? modelValue : undefined ;
1852
+ ctrl . $$invalidModelValue = ctrl . $valid ? undefined : modelValue ;
1853
+
1854
+ ngModelSet ( $scope , ctrl . $modelValue ) ;
1824
1855
forEach ( ctrl . $viewChangeListeners , function ( listener ) {
1825
1856
try {
1826
1857
listener ( ) ;
@@ -1894,26 +1925,31 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1894
1925
1895
1926
// model -> value
1896
1927
$scope . $watch ( function ngModelWatch ( ) {
1897
- var value = ngModelGet ( $scope ) ;
1928
+ var modelValue = ngModelGet ( $scope ) ;
1898
1929
1899
1930
// if scope model value and ngModel value are out of sync
1900
- if ( ctrl . $modelValue !== value ) {
1931
+ if ( ctrl . $modelValue !== modelValue &&
1932
+ ( isUndefined ( ctrl . $$invalidModelValue ) || ctrl . $$invalidModelValue != modelValue ) ) {
1901
1933
1902
1934
var formatters = ctrl . $formatters ,
1903
1935
idx = formatters . length ;
1904
1936
1905
- ctrl . $modelValue = value ;
1937
+ var viewValue = modelValue ;
1906
1938
while ( idx -- ) {
1907
- value = formatters [ idx ] ( value ) ;
1939
+ viewValue = formatters [ idx ] ( viewValue ) ;
1908
1940
}
1909
1941
1910
- if ( ctrl . $viewValue !== value ) {
1911
- ctrl . $viewValue = ctrl . $$lastCommittedViewValue = value ;
1942
+ ctrl . $$runValidators ( modelValue , viewValue ) ;
1943
+ ctrl . $modelValue = ctrl . $valid ? modelValue : undefined ;
1944
+ ctrl . $$invalidModelValue = ctrl . $valid ? undefined : modelValue ;
1945
+
1946
+ if ( ctrl . $viewValue !== viewValue ) {
1947
+ ctrl . $viewValue = ctrl . $$lastCommittedViewValue = viewValue ;
1912
1948
ctrl . $render ( ) ;
1913
1949
}
1914
1950
}
1915
1951
1916
- return value ;
1952
+ return modelValue ;
1917
1953
} ) ;
1918
1954
} ] ;
1919
1955
0 commit comments