Background: I’m working on an angular app that displays a list of articles. The list can be modified by various settings. One such setting is the sources of these articles. Think of a source as a news agency: an article originates from a particular source:
So when a user clicks on the "Sources" link, a dropdown menu should appear which contains a list of the sources. The user can select any combination of these sources. There are also a "Select all" and "Clear all" buttons to either select all the sources or deselect them all:
Problem: So every time a user selects or deselects a source, an http request should be sent to the server, and the list of the articles should be updated.
My problem is, I am not sure how to call the function that will send an http request (in the code snippets below it's called updateArticleList()
).
1) If I bind the function to ng-click
and set it on the label
tag:
<ul>
<li ng-repeat="source in sources">
<label ng-click="updateArticleList()">
<input type="checkbox" ng-model="source.selected">
{{source.title}}
</label>
</li>
</ul>
then a click on the label triggers the function twice (once for label
, and, apparently, once for input
). Not good.
2) If I bind the function to ng-change
on the input
tag:
<ul>
<li ng-repeat="source in sources">
<label>
<input type="checkbox" ng-model="source.selected"
ng-change="updateArticleList()">
{{source.title}}
</label>
</li>
</ul>
then once I click on "Select all" or "Clear" buttons, this will change the state of all the checkboxes and send a lot of http requests. Not good either.
Right now, I am trying to solve this using setTimeout
to filter out a burst of calls to the function to one, like so (example for calling the function through ng-click):
var requestAllowed = true;
var debounceRequests = function(){
requestAllowed = false;
setTimeout(function(){
requestAllowed = true;
}, 5);
};
scope.updateArticleList = function(){
if (requestAllowed === true){
// prevent the second call to the function from ng-click
debounceRequests();
// also, give time for the input to register ng-click on the label
setTimeout(function(){
// finally, send an http request
getArticles();
}, 5);
}
};
But this looks dirty.
So, my question is, what would be a good way to make http requests in this situation?
Preferably, without using extra js libraries.
==================
UPDATED:
Here's the function that is triggered by "Select All":
scope.selectAllSources = function(){
scope.sources.forEach(function(source){
source.selected = true;
});
scope.updateArticleList();
};