6
6
DIRTY_CLASS: true,
7
7
UNTOUCHED_CLASS: true,
8
8
TOUCHED_CLASS: true,
9
+ $ModelOptionsProvider: true,
9
10
*/
10
11
11
12
var VALID_CLASS = 'ng-valid' ,
@@ -217,8 +218,8 @@ is set to `true`. The parse error is stored in `ngModel.$error.parse`.
217
218
*
218
219
*
219
220
*/
220
- var NgModelController = [ '$scope' , '$exceptionHandler' , '$attrs' , '$element' , '$parse' , '$animate' , '$timeout' , '$rootScope' , '$q' , '$interpolate' ,
221
- function ( $scope , $exceptionHandler , $attr , $element , $parse , $animate , $timeout , $rootScope , $q , $interpolate ) {
221
+ var NgModelController = [ '$scope' , '$exceptionHandler' , '$attrs' , '$element' , '$parse' , '$animate' , '$timeout' , '$rootScope' , '$q' , '$interpolate' , '$modelOptions' ,
222
+ function ( $scope , $exceptionHandler , $attr , $element , $parse , $animate , $timeout , $rootScope , $q , $interpolate , $modelOptions ) {
222
223
this . $viewValue = Number . NaN ;
223
224
this . $modelValue = Number . NaN ;
224
225
this . $$rawModelValue = undefined ; // stores the parsed modelValue / model set from scope regardless of validity.
@@ -237,7 +238,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
237
238
this . $$success = { } ; // keep valid keys here
238
239
this . $pending = undefined ; // keep pending keys here
239
240
this . $name = $interpolate ( $attr . name || '' , false ) ( $scope ) ;
240
-
241
+ this . $options = $modelOptions . defaultOptions ;
241
242
242
243
var parsedNgModel = $parse ( $attr . ngModel ) ,
243
244
parsedNgModelAssign = parsedNgModel . assign ,
@@ -246,9 +247,10 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
246
247
pendingDebounce = null ,
247
248
ctrl = this ;
248
249
249
- this . $$setOptions = function ( options ) {
250
- ctrl . $options = options ;
251
- if ( options && options . getterSetter ) {
250
+
251
+ this . $$initGetterSetters = function ( ) {
252
+
253
+ if ( ctrl . $options . getterSetter ) {
252
254
var invokeModelGetter = $parse ( $attr . ngModel + '()' ) ,
253
255
invokeModelSetter = $parse ( $attr . ngModel + '($$$p)' ) ;
254
256
@@ -272,6 +274,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
272
274
}
273
275
} ;
274
276
277
+
275
278
/**
276
279
* @ngdoc method
277
280
* @name ngModel.NgModelController#$render
@@ -523,7 +526,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
523
526
var prevValid = ctrl . $valid ;
524
527
var prevModelValue = ctrl . $modelValue ;
525
528
526
- var allowInvalid = ctrl . $options && ctrl . $options . allowInvalid ;
529
+ var allowInvalid = ctrl . $options . allowInvalid ;
527
530
528
531
ctrl . $$runValidators ( parserValid , modelValue , viewValue , function ( allValid ) {
529
532
// If there was no change in validity, don't update the model
@@ -683,7 +686,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
683
686
ctrl . $modelValue = ngModelGet ( $scope ) ;
684
687
}
685
688
var prevModelValue = ctrl . $modelValue ;
686
- var allowInvalid = ctrl . $options && ctrl . $options . allowInvalid ;
689
+ var allowInvalid = ctrl . $options . allowInvalid ;
687
690
ctrl . $$rawModelValue = modelValue ;
688
691
689
692
if ( allowInvalid ) {
@@ -764,25 +767,19 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
764
767
*/
765
768
this . $setViewValue = function ( value , trigger ) {
766
769
ctrl . $viewValue = value ;
767
- if ( ! ctrl . $options || ctrl . $options . updateOnDefault ) {
770
+ if ( ctrl . $options . updateOnDefault ) {
768
771
ctrl . $$debounceViewValueCommit ( trigger ) ;
769
772
}
770
773
} ;
771
774
772
775
this . $$debounceViewValueCommit = function ( trigger ) {
773
- var debounceDelay = 0 ,
774
- options = ctrl . $options ,
775
- debounce ;
776
-
777
- if ( options && isDefined ( options . debounce ) ) {
778
- debounce = options . debounce ;
779
- if ( isNumber ( debounce ) ) {
780
- debounceDelay = debounce ;
781
- } else if ( isNumber ( debounce [ trigger ] ) ) {
782
- debounceDelay = debounce [ trigger ] ;
783
- } else if ( isNumber ( debounce [ 'default' ] ) ) {
784
- debounceDelay = debounce [ 'default' ] ;
785
- }
776
+ var options = ctrl . $options ,
777
+ debounceDelay = options . debounce ;
778
+
779
+ if ( isNumber ( debounceDelay [ trigger ] ) ) {
780
+ debounceDelay = debounceDelay [ trigger ] ;
781
+ } else if ( isNumber ( debounceDelay [ 'default' ] ) ) {
782
+ debounceDelay = debounceDelay [ 'default' ] ;
786
783
}
787
784
788
785
$timeout . cancel ( pendingDebounce ) ;
@@ -1014,9 +1011,14 @@ var ngModelDirective = ['$rootScope', function($rootScope) {
1014
1011
return {
1015
1012
pre : function ngModelPreLink ( scope , element , attr , ctrls ) {
1016
1013
var modelCtrl = ctrls [ 0 ] ,
1017
- formCtrl = ctrls [ 1 ] || nullFormCtrl ;
1014
+ formCtrl = ctrls [ 1 ] || nullFormCtrl ,
1015
+ optionsCtrl = ctrls [ 2 ] ;
1018
1016
1019
- modelCtrl . $$setOptions ( ctrls [ 2 ] && ctrls [ 2 ] . $options ) ;
1017
+ if ( optionsCtrl ) {
1018
+ modelCtrl . $options = optionsCtrl . $options ;
1019
+ }
1020
+
1021
+ modelCtrl . $$initGetterSetters ( ) ;
1020
1022
1021
1023
// notify others, especially parent forms
1022
1024
formCtrl . $addControl ( modelCtrl ) ;
@@ -1033,7 +1035,7 @@ var ngModelDirective = ['$rootScope', function($rootScope) {
1033
1035
} ,
1034
1036
post : function ngModelPostLink ( scope , element , attr , ctrls ) {
1035
1037
var modelCtrl = ctrls [ 0 ] ;
1036
- if ( modelCtrl . $options && modelCtrl . $options . updateOn ) {
1038
+ if ( modelCtrl . $options . updateOn ) {
1037
1039
element . on ( modelCtrl . $options . updateOn , function ( ev ) {
1038
1040
modelCtrl . $$debounceViewValueCommit ( ev && ev . type ) ;
1039
1041
} ) ;
@@ -1077,7 +1079,7 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
1077
1079
* then it will inherit that setting from the first ngModelOptions directive found by traversing up the
1078
1080
* DOM tree.
1079
1081
*
1080
- * For example in the following fragment of HTML ...
1082
+ * For example given the following fragment of HTML
1081
1083
*
1082
1084
*
1083
1085
* ```html
@@ -1088,7 +1090,7 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
1088
1090
* </div>
1089
1091
* ```
1090
1092
*
1091
- * ... the `input` element will effective have the following settings ...
1093
+ * the `input` element will have the following settings
1092
1094
*
1093
1095
* ```js
1094
1096
* { allowInvalid: true, updateOn: 'default' }
@@ -1205,7 +1207,7 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
1205
1207
* ## Connecting to the scope
1206
1208
*
1207
1209
* By setting the `getterSetter` property to true you are telling ngModel that the `ngModel` expression
1208
- * on the scope actually refers to a "getter/setter" function rather than the actual value itself.
1210
+ * on the scope refers to a "getter/setter" function rather than the value itself.
1209
1211
*
1210
1212
* The following example shows how to bind to getter/setters:
1211
1213
*
@@ -1256,7 +1258,7 @@ var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
1256
1258
* `<input type="date">`, `<input type="time">`, ... . Right now, the only supported value is `'UTC'`,
1257
1259
* otherwise the default timezone of the browser will be used.
1258
1260
*/
1259
- var ngModelOptionsDirective = function ( ) {
1261
+ var ngModelOptionsDirective = [ '$modelOptions' , function ( $modelOptions ) {
1260
1262
return {
1261
1263
restrict : 'A' ,
1262
1264
// ngModelOptions needs to run before ngModel and input directives
@@ -1266,10 +1268,10 @@ var ngModelOptionsDirective = function() {
1266
1268
link : {
1267
1269
pre : function ngModelOptionsPreLinkFn ( scope , element , attrs , ctrls ) {
1268
1270
var optionsCtrl = ctrls [ 0 ] ;
1269
- var parentOptions = ctrls [ 1 ] ? ctrls [ 1 ] . $localOptions : { } ;
1271
+ var parentOptions = ctrls [ 1 ] ? ctrls [ 1 ] . $localOptions : $modelOptions . defaultOptions ;
1270
1272
1271
1273
// Store the raw options taken from the attributes (after inheriting parent options)
1272
- optionsCtrl . $localOptions = extend ( { } , scope . $eval ( attrs . ngModelOptions ) , parentOptions ) ;
1274
+ optionsCtrl . $localOptions = extend ( { } , parentOptions , scope . $eval ( attrs . ngModelOptions ) ) ;
1273
1275
1274
1276
// Make a copy and manipulate the options to make them ready to be consumed
1275
1277
optionsCtrl . $options = copy ( optionsCtrl . $localOptions ) ;
@@ -1288,7 +1290,47 @@ var ngModelOptionsDirective = function() {
1288
1290
}
1289
1291
}
1290
1292
} ;
1291
- } ;
1293
+ } ] ;
1294
+
1295
+
1296
+ /**
1297
+ * @ngdoc service
1298
+ * @name $modelOptions
1299
+ * @description
1300
+ *
1301
+ * This service provides support to the {@link ngModelOptions} directive.
1302
+ *
1303
+ * Here, you can change the default settings from which {@link ngModelOptions}
1304
+ * directives inherit.
1305
+ *
1306
+ * See the {@link ngModelOptions} directive for a list of the available options.
1307
+ *
1308
+ */
1309
+ function $ModelOptionsProvider ( ) {
1310
+ return {
1311
+ $get : function ( ) {
1312
+ return {
1313
+ /**
1314
+ * @ngdoc property
1315
+ * @name $modelOptions#defaultOptions
1316
+ * @type {Object }
1317
+ * @description
1318
+ * The default options to fall back on when there are no more ngModelOption
1319
+ * directives as ancestors
1320
+ *
1321
+ * The initial default options are:
1322
+ *
1323
+ * * `updateOneDefault`: `true`
1324
+ * * `debounce`: `0`
1325
+ */
1326
+ defaultOptions : {
1327
+ updateOnDefault : true ,
1328
+ debounce : 0
1329
+ }
1330
+ } ;
1331
+ }
1332
+ } ;
1333
+ }
1292
1334
1293
1335
1294
1336
0 commit comments