@@ -877,7 +877,7 @@ function addNativeHtml5Validators(ctrl, validatorName, element) {
877
877
}
878
878
}
879
879
880
- function textInputType ( scope , element , attr , ctrl , $sniffer , $browser ) {
880
+ function textInputType ( scope , element , attr , ctrl , options , $sniffer , $browser ) {
881
881
var validity = element . prop ( 'validity' ) ;
882
882
// In composition mode, users are still inputing intermediate text buffer,
883
883
// hold the listener until composition is done.
@@ -1067,8 +1067,8 @@ function createDateParser(regexp, mapping) {
1067
1067
}
1068
1068
1069
1069
function createDateInputType ( type , regexp , parseDate , format ) {
1070
- return function dynamicDateInputType ( scope , element , attr , ctrl , $sniffer , $browser , $filter ) {
1071
- textInputType ( scope , element , attr , ctrl , $sniffer , $browser ) ;
1070
+ return function dynamicDateInputType ( scope , element , attr , ctrl , options , $sniffer , $browser , $filter ) {
1071
+ textInputType ( scope , element , attr , ctrl , options , $sniffer , $browser ) ;
1072
1072
1073
1073
ctrl . $parsers . push ( function ( value ) {
1074
1074
if ( ctrl . $isEmpty ( value ) ) {
@@ -1118,8 +1118,8 @@ function createDateInputType(type, regexp, parseDate, format) {
1118
1118
} ;
1119
1119
}
1120
1120
1121
- function numberInputType ( scope , element , attr , ctrl , $sniffer , $browser ) {
1122
- textInputType ( scope , element , attr , ctrl , $sniffer , $browser ) ;
1121
+ function numberInputType ( scope , element , attr , ctrl , options , $sniffer , $browser ) {
1122
+ textInputType ( scope , element , attr , ctrl , options , $sniffer , $browser ) ;
1123
1123
1124
1124
ctrl . $parsers . push ( function ( value ) {
1125
1125
var empty = ctrl . $isEmpty ( value ) ;
@@ -1163,8 +1163,8 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
1163
1163
} ) ;
1164
1164
}
1165
1165
1166
- function urlInputType ( scope , element , attr , ctrl , $sniffer , $browser ) {
1167
- textInputType ( scope , element , attr , ctrl , $sniffer , $browser ) ;
1166
+ function urlInputType ( scope , element , attr , ctrl , options , $sniffer , $browser ) {
1167
+ textInputType ( scope , element , attr , ctrl , options , $sniffer , $browser ) ;
1168
1168
1169
1169
var urlValidator = function ( value ) {
1170
1170
return validate ( ctrl , 'url' , ctrl . $isEmpty ( value ) || URL_REGEXP . test ( value ) , value ) ;
@@ -1174,8 +1174,8 @@ function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
1174
1174
ctrl . $parsers . push ( urlValidator ) ;
1175
1175
}
1176
1176
1177
- function emailInputType ( scope , element , attr , ctrl , $sniffer , $browser ) {
1178
- textInputType ( scope , element , attr , ctrl , $sniffer , $browser ) ;
1177
+ function emailInputType ( scope , element , attr , ctrl , options , $sniffer , $browser ) {
1178
+ textInputType ( scope , element , attr , ctrl , options , $sniffer , $browser ) ;
1179
1179
1180
1180
var emailValidator = function ( value ) {
1181
1181
return validate ( ctrl , 'email' , ctrl . $isEmpty ( value ) || EMAIL_REGEXP . test ( value ) , value ) ;
@@ -1185,7 +1185,7 @@ function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
1185
1185
ctrl . $parsers . push ( emailValidator ) ;
1186
1186
}
1187
1187
1188
- function radioInputType ( scope , element , attr , ctrl ) {
1188
+ function radioInputType ( scope , element , attr , ctrl , options ) {
1189
1189
// make the name unique, if not defined
1190
1190
if ( isUndefined ( attr . name ) ) {
1191
1191
element . attr ( 'name' , nextUid ( ) ) ;
@@ -1207,7 +1207,7 @@ function radioInputType(scope, element, attr, ctrl) {
1207
1207
attr . $observe ( 'value' , ctrl . $render ) ;
1208
1208
}
1209
1209
1210
- function checkboxInputType ( scope , element , attr , ctrl ) {
1210
+ function checkboxInputType ( scope , element , attr , ctrl , options ) {
1211
1211
var trueValue = attr . ngTrueValue ,
1212
1212
falseValue = attr . ngFalseValue ;
1213
1213
@@ -1380,10 +1380,10 @@ function checkboxInputType(scope, element, attr, ctrl) {
1380
1380
var inputDirective = [ '$browser' , '$sniffer' , '$filter' , function ( $browser , $sniffer , $filter ) {
1381
1381
return {
1382
1382
restrict : 'E' ,
1383
- require : '?ngModel' ,
1384
- link : function ( scope , element , attr , ctrl ) {
1385
- if ( ctrl ) {
1386
- ( inputType [ lowercase ( attr . type ) ] || inputType . text ) ( scope , element , attr , ctrl , $sniffer ,
1383
+ require : [ '?ngModel' , '^?ngModelOptions' ] ,
1384
+ link : function ( scope , element , attr , ctrls ) {
1385
+ if ( ctrls [ 0 ] ) {
1386
+ ( inputType [ lowercase ( attr . type ) ] || inputType . text ) ( scope , element , attr , ctrls [ 0 ] , ctrls [ 1 ] , $sniffer ,
1387
1387
$browser , $filter ) ;
1388
1388
}
1389
1389
}
@@ -1529,8 +1529,8 @@ var VALID_CLASS = 'ng-valid',
1529
1529
*
1530
1530
*
1531
1531
*/
1532
- var NgModelController = [ '$scope' , '$exceptionHandler' , '$attrs' , '$element' , '$parse' , '$animate' ,
1533
- function ( $scope , $exceptionHandler , $attr , $element , $parse , $animate ) {
1532
+ var NgModelController = [ '$scope' , '$exceptionHandler' , '$attrs' , '$element' , '$parse' , '$animate' , '$timeout' ,
1533
+ function ( $scope , $exceptionHandler , $attr , $element , $parse , $animate , $timeout ) {
1534
1534
this . $viewValue = Number . NaN ;
1535
1535
this . $modelValue = Number . NaN ;
1536
1536
this . $parsers = [ ] ;
@@ -1541,9 +1541,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1541
1541
this . $valid = true ;
1542
1542
this . $invalid = false ;
1543
1543
this . $name = $attr . name ;
1544
+ this . $options = { debounce : { } } ;
1545
+
1544
1546
1545
1547
var ngModelGet = $parse ( $attr . ngModel ) ,
1546
- ngModelSet = ngModelGet . assign ;
1548
+ ngModelSet = ngModelGet . assign ,
1549
+ pendingDebounce = null ;
1547
1550
1548
1551
if ( ! ngModelSet ) {
1549
1552
throw minErr ( 'ngModel' ) ( 'nonassign' , "Expression '{0}' is non-assignable. Element: {1}" ,
@@ -1678,7 +1681,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1678
1681
*
1679
1682
* @param {string } value Value from the view.
1680
1683
*/
1681
- this . $setViewValue = function ( value ) {
1684
+ this . $realSetViewValue = function ( value ) {
1682
1685
this . $viewValue = value ;
1683
1686
1684
1687
// change to dirty
@@ -1706,6 +1709,24 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1706
1709
} ) ;
1707
1710
}
1708
1711
} ;
1712
+ this . $setViewValue = function ( value , trigger ) {
1713
+ var that = this ;
1714
+ trigger = trigger || 'default' ;
1715
+ var debounceDelay = ( isObject ( this . $options . debounce ) ? this . $options . debounce [ trigger ] : this . $options . debounce ) || 0 ;
1716
+
1717
+ if ( pendingDebounce ) {
1718
+ $timeout . cancel ( pendingDebounce ) ;
1719
+ pendingDebounce = null ;
1720
+ }
1721
+ if ( debounceDelay ) {
1722
+ pendingDebounce = $timeout ( function ( ) {
1723
+ pendingDebounce = null ;
1724
+ that . $realSetViewValue ( value ) ;
1725
+ } , debounceDelay ) ;
1726
+ } else {
1727
+ that . $realSetViewValue ( value ) ;
1728
+ }
1729
+ } ;
1709
1730
1710
1731
// model -> value
1711
1732
var ctrl = this ;
@@ -1716,6 +1737,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1716
1737
// if scope model value and ngModel value are out of sync
1717
1738
if ( ctrl . $modelValue !== value ) {
1718
1739
1740
+ // Cancel any pending debounced update
1741
+ if ( pendingDebounce ) {
1742
+ $timeout . cancel ( pendingDebounce ) ;
1743
+ pendingDebounce = null ;
1744
+ }
1745
+
1719
1746
var formatters = ctrl . $formatters ,
1720
1747
idx = formatters . length ;
1721
1748
@@ -1844,7 +1871,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
1844
1871
*/
1845
1872
var ngModelDirective = function ( ) {
1846
1873
return {
1847
- require : [ 'ngModel' , '^?form' ] ,
1874
+ require : [ 'ngModel' , '^?form' , '^?ngModelOptions' ] ,
1848
1875
controller : NgModelController ,
1849
1876
link : function ( scope , element , attr , ctrls ) {
1850
1877
// notify others, especially parent forms
@@ -1854,6 +1881,11 @@ var ngModelDirective = function() {
1854
1881
1855
1882
formCtrl . $addControl ( modelCtrl ) ;
1856
1883
1884
+ // Pass the ng-model-options to the ng-model controller
1885
+ if ( ctrls [ 2 ] ) {
1886
+ modelCtrl . $options = ctrls [ 2 ] . $options ;
1887
+ }
1888
+
1857
1889
scope . $on ( '$destroy' , function ( ) {
1858
1890
formCtrl . $removeControl ( modelCtrl ) ;
1859
1891
} ) ;
@@ -2122,3 +2154,12 @@ var ngValueDirective = function() {
2122
2154
}
2123
2155
} ;
2124
2156
} ;
2157
+
2158
+
2159
+ var ngModelOptionsDirective = function ( ) {
2160
+ return {
2161
+ controller : function ( $scope , $attrs ) {
2162
+ this . $options = $scope . $eval ( $attrs . ngModelOptions ) ;
2163
+ }
2164
+ } ;
2165
+ } ;
0 commit comments