Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
feat(ngModelOptions): allow to debounce 'default' only and add deboun…
Browse files Browse the repository at this point in the history
…ce catch-all

Closes #15411

BREAKING CHANGE:

the 'default' key in 'debounce' now only debounces the default event, i.e. the event
that is added as an update trigger by the different input directives automatically.

Previously, it also applied to other update triggers defined in 'updateOn' that
did not have a corresponding key in the 'debounce'.

This behavior is now supported via a special wildcard / catch-all key: '*'.

See the following example:

Pre-1.7:
'mouseup' is debounced by 500 milliseconds because 'default' is applied.
```
ng-model-options="{
  updateOn: 'default blur mouseup',
  debounce: { 'default': 500, 'blur': 0 }
}
```

1.7:
'mouseup' is debounced by 1000 milliseconds because '*' is applied.
```
ng-model-options="{
  updateOn: 'default blur mouseup',
  debounce: { 'default': 500, 'blur': 0, '*': 1000 }
}
```
  • Loading branch information
Narretz committed Nov 21, 2017
1 parent aa3f951 commit 4d12164
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 3 deletions.
4 changes: 3 additions & 1 deletion src/ng/directive/ngModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -838,8 +838,10 @@ 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);
Expand Down
8 changes: 8 additions & 0 deletions src/ng/directive/ngModelOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 34 additions & 2 deletions test/ng/directive/ngModelOptionsSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 allow to set * as debounce key to catch all unlisted events',
function() {
var inputElm = helper.compileInput(
'<input type="text" ng-model="name" name="alias" ' +
'ng-model-options="{' +
'updateOn: \'default blur mouseup\', ' +
'debounce: { default: 10000, blur: 5000, \'*\': 15000 }' +
'}"' +
'/>');

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');
});

Expand Down

0 comments on commit 4d12164

Please sign in to comment.