0

On one of the pages in our AngularJS 1.* application, I am looking at a text input1 whose debounce is set to a value greater than zero. It is configured roughly like this:

<input type="text" data-ng-model="data.value1"
       ng-model-options="{ updateOn: 'default blur', debounce: { default: 2500, blur: 0 }}"
       data-ng-change="onValueChanged()">

The data entered via that text input is processed when clicking a button, or when hitting the Enter key.

Now, the issue is that when the user hits Enter immediately after changing the value, the new value is not yet in the model due to the debounce setting.

The only hint towards a solution that I could find talks about using ngSubmit instead of ngClick, but we are neither using a form element nor ngClick (the latter at least not where it matters). The Enter keypress is captured in a custom directive via a keydown event.

Can I somehow force AngularJS to skip the debounce period and immediately update the model on my command in the handler of that keydown event?

Note that an obvious workaround would be to use a $timeout slightly higher than the debounce delay in the keydown handler, so as to be sure that the model has been updated. That feels really hacky to me, though, and also conflicts with the user expectation to get some immediate reaction when hitting the Enter key.


1: In fact, it's a dynamically generated UI that may contain any number of such text inputs in nested containers.

Satpal
  • 132,252
  • 13
  • 159
  • 168
O. R. Mapper
  • 20,083
  • 9
  • 69
  • 114
  • 1
    Just curious, Why are you using _debounce_ in first place? when you want to override – Satpal Feb 07 '18 at 07:50
  • 1
    @Satpal: I only want to override the debounce in the specific event of a *Return* key press. The people who have developed this part of the UI insist the debounce is essential in all other situations due to various pieces of logic that are coupled to the model and changes therein. – O. R. Mapper Feb 07 '18 at 08:12

2 Answers2

0

In the end, I dropped the AngularJS-based debounce option.

Instead, I used _.debounce from the lodash library in any place that gets invoked upon changes to the model of my inputs. _.debounce provides a flush() method that will force the immediate invocation of the debounced function if appropriate. So, I am now calling that method when reacting to keystrokes of the Enter key.

O. R. Mapper
  • 20,083
  • 9
  • 69
  • 114
0

I managed to workaround the problem with a custom directive firing a 'submit' event :

angular.module('...')
.directive('submitListener', () =>
    ({
        restrict: 'A',
        require: 'ngModel',
        link(scope, elem, attrs, ngModelCtrl) {
            elem.on('keyup', ($event) => {
                if ($event.keyCode === 13) {
                    console.log(`submitted !`)
                    ngModelCtrl.$setViewValue(elem.val(), 'submit')
                }
            })
        },
    })
)

and using the directive on the input and configuring the event in the ng-model-options + debounce config :

<input type="text" data-ng-model="data.value1"
   ng-model-options="{ updateOn: 'default blur submit', debounce: { default: 2500, blur: 0, submit: 0 }}"
   submit-listener
   data-ng-change="onValueChanged()">
pedro
  • 11
  • 2