I have a performance issue that I can't seem to address. I have an instant search but it's somewhat laggy, since it starts searching on each keyup()
.
JS:
var App = angular.module('App', []);
App.controller('DisplayController', function($scope, $http) {
$http.get('data.json').then(function(result){
$scope.entries = result.data;
});
});
HTML:
<input id="searchText" type="search" placeholder="live search..." ng-model="searchText" />
<div class="entry" ng-repeat="entry in entries | filter:searchText">
<span>{{entry.content}}</span>
</div>
The JSON data isn't even that large, 300KB only, I think what I need to accomplish is to put a delay of ~1 sec on the search to wait for the user to finish typing, instead of performing the action on each keystroke. AngularJS does this internally, and after reading docs and other topics on here I couldn't find a specific answer.
I would appreciate any pointers on how I can delay the instant search.
For those who uses keyup/keydown in the HTML markup. This doesn't uses watch.
JS
HTML
Debounced / throttled model updates for angularjs : http://jsfiddle.net/lgersman/vPsGb/3/
In your case there is nothing more to do than using the directive in the jsfiddle code like this:
Its basically a small piece of code consisting of a single angular directive named "ng-ampere-debounce" utilizing http://benalman.com/projects/jquery-throttle-debounce-plugin/ which can be attached to any dom element. The directive reorders the attached event handlers so that it can control when to throttle events.
You can use it for throttling/debouncing * model angular updates * angular event handler ng-[event] * jquery event handlers
Have a look : http://jsfiddle.net/lgersman/vPsGb/3/
The directive will be part of the Orangevolt Ampere framework (https://github.com/lgersman/jquery.orangevolt-ampere).
I think the easiest way here is to preload the json or load it once on
$dirty
and then the filter search will take care of the rest. This'll save you the extra http calls and its much faster with preloaded data. Memory will hurt, but its worth it.I solved this problem with a directive that basicly what it does is to bind the real ng-model on a special attribute which I watch in the directive, then using a debounce service I update my directive attribute, so the user watch on the variable that he bind to debounce-model instead of ng-model.
Usage:
And in the controller :
Demo in jsfiddle: http://jsfiddle.net/6K7Kd/37/
the $debounce service can be found here: http://jsfiddle.net/Warspawn/6K7Kd/
Inspired by eventuallyBind directive http://jsfiddle.net/fctZH/12/
Another solution is to add a delay functionality to model update. The simple directive seems to do a trick:
Usage:
So you just use
delayed-model
in place ofng-model
and define desireddata-delay
.Demo: http://plnkr.co/edit/OmB4C3jtUD2Wjq5kzTSU?p=preview
In Angular 1.3 I would do this:
HTML:
Controller:
Basically you're telling angular to run
myDebouncedFunction()
, when the themsg
scope variable changes. The attributeng-model-options="{debounce: 1000}"
makes sure thatmsg
can only update once a second.