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