Samantha J T Star
Samantha J T Star

Reputation: 32808

Can I put a timer on a .on('keyup' to cut down the number of updates?

I have the following code working:

$wmdInput.on('keyup', function () {
    var rawContent = $wmdInput.val();
    scope.$apply(function () {
        ngModel.$setViewValue(rawContent);
    });
});

However it seems to slow down my entering of characters. Is there some way I could put a timeout on this so that all the data is saved but it just does not do it more than for example once every two seconds?

Upvotes: 4

Views: 338

Answers (4)

ach
ach

Reputation: 6234

If you can use lodash (which you should) just wrap the function in _.debounce:

$wmdInput.on('keyup', _.debounce(function () {
    var rawContent = $wmdInput.val();
    scope.$apply(function () {
        ngModel.$setViewValue(rawContent);
    });
}, 300));

This will cause the function to be called only when the user has stopped typing for 300 ms -- obviously you should tweak the wait to whatever works best for you.

IMO debouncing is more appropriate than throttling in this case.

Upvotes: 2

Lucius
Lucius

Reputation: 2872

Pure AngularJS approach

var promise;
$wmdInput.on('keyup', function () {
    $timeout.cancel(promise);
    promise = $timeout(function() {
        var rawContent = $wmdInput.val();
        ngModel.$setViewValue(rawContent);
    }, 2000);
});

Upvotes: 3

Travis
Travis

Reputation: 10547

Reactive Extensions for JavaScript might be an option for you to use. You can setup the keyup event as an event source and throttle the events. In fact the README has an example that seems similar to what you want...

var $input = $('#input'),
    $results = $('#results');

/* Only get the value from each key up */
var keyups = Rx.Observable.fromEvent(input, 'keyup')
    .map(function (e) {
        return e.target.value;
    })
    .filter(function (text) {
        return text.length > 2;
    });

/* Now throttle/debounce the input for 500ms */
var throttled = keyups
     .throttle(500 /* ms */);

/* Now get only distinct values, so we eliminate 
   the arrows and other control characters */
var distinct = throttled
    .distinctUntilChanged();

In your case you may not want the filter for length > 2, so just remove that expression. Regardless, you can just tack on a subscribe at the end to process your event

distinct.subscribe(function(value) {
    scope.$apply(function () {
        ngModel.$setViewValue(value);
    });
});

And there are bindings for AngularJS for you as well.

Upvotes: 1

Alexander
Alexander

Reputation: 20224

in the function above, add two lines to:

  • remove keyup event from wmdInput.
  • set timer to add keyup event to wmdInput after 2 seconds.

Upvotes: -2

Related Questions