diff --git a/src/ng/directive/ngModel.js b/src/ng/directive/ngModel.js index 5e9aa4a38628..8afa3da7f64a 100644 --- a/src/ng/directive/ngModel.js +++ b/src/ng/directive/ngModel.js @@ -838,8 +838,12 @@ NgModelController.prototype = { if (isNumber(debounceDelay[trigger])) { debounceDelay = debounceDelay[trigger]; - } else if (isNumber(debounceDelay['default'])) { + } else if (isNumber(debounceDelay['default']) && + this.$options.getOption('updateOn').indexOf(trigger) === -1 + ) { debounceDelay = debounceDelay['default']; + } else if (isNumber(debounceDelay['*'])) { + debounceDelay = debounceDelay['*']; } this.$$timeout.cancel(this.$$pendingDebounce); diff --git a/src/ng/directive/ngModelOptions.js b/src/ng/directive/ngModelOptions.js index 47c51e8460a5..2defcee0d128 100644 --- a/src/ng/directive/ngModelOptions.js +++ b/src/ng/directive/ngModelOptions.js @@ -321,6 +321,14 @@ defaultModelOptions = new ModelOptions({ * debounce: { 'default': 500, 'blur': 0 } * }" * ``` + * You can use the `*` key to specify a debounce value that applies to all events that are not + * specifically listed. In the following example, `mouseup` would have a debounce delay of 1000: + * ``` + * ng-model-options="{ + * updateOn: 'default blur mouseup', + * debounce: { 'default': 500, 'blur': 0, '*': 1000 } + * }" + * ``` * - `allowInvalid`: boolean value which indicates that the model can be set with values that did * not validate correctly instead of the default behavior of setting the model to undefined. * - `getterSetter`: boolean value which determines whether or not to treat functions bound to diff --git a/test/ng/directive/ngModelOptionsSpec.js b/test/ng/directive/ngModelOptionsSpec.js index f4142ae217ee..3814ba2bc5ca 100644 --- a/test/ng/directive/ngModelOptionsSpec.js +++ b/test/ng/directive/ngModelOptionsSpec.js @@ -498,9 +498,41 @@ describe('ngModelOptions', function() { helper.changeInputValueTo('c'); browserTrigger(helper.inputElm, 'mouseup'); - // counter-intuitively `default` in `debounce` is a catch-all + // `default` in `debounce` only affects the event triggers that are not defined in updateOn + expect($rootScope.name).toEqual('c'); + }); + + + it('should use the value of * to debounce all unspecified events', + function() { + var inputElm = helper.compileInput( + ''); + + helper.changeInputValueTo('a'); + expect($rootScope.name).toBeUndefined(); + $timeout.flush(6000); + expect($rootScope.name).toBeUndefined(); + $timeout.flush(4000); + expect($rootScope.name).toEqual('a'); + + helper.changeInputValueTo('b'); + browserTrigger(inputElm, 'blur'); + $timeout.flush(4000); + expect($rootScope.name).toEqual('a'); + $timeout.flush(2000); expect($rootScope.name).toEqual('b'); - $timeout.flush(10000); + + helper.changeInputValueTo('c'); + browserTrigger(helper.inputElm, 'mouseup'); + expect($rootScope.name).toEqual('b'); + $timeout.flush(10000); // flush default + expect($rootScope.name).toEqual('b'); + $timeout.flush(5000); expect($rootScope.name).toEqual('c'); });