Skip to content

Commit

Permalink
feat(ngModelOptions): add debounce catch-all + allow debouncing 'defa…
Browse files Browse the repository at this point in the history
…ult' only

Closes angular#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 also debounced by 500 milliseconds because 'default' is applied:
```
ng-model-options="{
  updateOn: 'default blur mouseup',
  debounce: { 'default': 500, 'blur': 0 }
}
```

1.7:
The pre-1.7 behavior can be re-created by setting '*' as a catch-all debounce value:
```
ng-model-options="{
  updateOn: 'default blur mouseup',
  debounce: { '*': 500, 'blur': 0 }
}
```

In contrast, when 'default' is used, 'blur' and 'mouseup' are not debounced:
```
ng-model-options="{
  updateOn: 'default blur mouseup',
  debounce: { 'default': 500 }
}
```
  • Loading branch information
Narretz committed Nov 21, 2017
1 parent aa3f951 commit 597f52f
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
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
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
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 597f52f

Please sign in to comment.