Reputation: 4289
I've an issue with multiple ajax requests. For example I've a form with a button, and onclick
it runs a service which essentially load list of items in a table; for now it should load a single item into a table when I hit the button.
However, when I hit the button multiple times, the same item is duplicated when its loaded.
How can I prevent while there is still no callback from the first one?
var getItems = function () {
var def = $q.defer();
Items.get().then(function (items) {
def.resolve(items);
}, function (err) {
...
});
};
Not sure if this is a solution, but when I write above code like this:
var def = false;
var getItems = function () {
def = $q.defer();
Items.get().then(function (items) {
def.resolve(items);
}, function (err) {
...
});
};
This stops the duplication when I initialize the def = false
, not sure if this is the correct approach by resetting the previous/old request to false
?
Upvotes: 0
Views: 5250
Reputation: 18065
you can create a reusable directive so that on any button which is clickable, it doesnt get pressed twice
app.directive('clickAndDisable', function() {
return {
scope: {
clickAndDisable: '&'
},
link: function(scope, iElement, iAttrs) {
iElement.bind('click', function() {
iElement.prop('disabled',true);
scope.clickAndDisable().finally(function() {
iElement.prop('disabled',false);
})
});
}
};
});
This can be used on a button as follows:
<button click-and-disable="functionThatReturnsPromise()">Click me</button>
Upvotes: 0
Reputation: 11755
You can put a lock on the function to prevent the code from running multiple times at once or at all:
// your service
$scope.isRunning = false;
var getItems = function () {
if(!$scope.isRunning){
$scope.isRunning = true;
var def = $q.defer();
Items.get().then(function (items) {
def.resolve(items);
}, function (err) {
...
}).finally(function(){
//$scope.isRunning = false; // once done, reset isRunning to allow to run again. If you want it to run just once then exclude this line
});
}
};
Unsure how you want to handle the button in terms of being clicked multiple times
You can hide it on click:
<button ng-hide="isRunning">Stuff</button>
You can disable it on click:
<button ng-disabled="isRunning">Stuff</button>
if disabling, you should probably give feedback like changing opacity:
<button ng-disabled="isRunning" ng-class='{"opacity-half": isRunning}'>Stuff</button>
.opacity-half { opacity: 0.5 }
Upvotes: 3
Reputation: 3061
the below code should do the trick I am avoiding some angular specific syntax hope that helps;
function yourContoller(/*all injectables*/) {
var requesting = false;
$scope.buttonClick = function() {
if (!requesting) {
requesting = true;
yourService.getItems().then(function(response) {
/*your code to handle response*/
requesting = false;
});
}
};
}
if you want to disable a button in the view you can expose this variable by simply using scope ($scope.requesting = false;
) with ng-disabled
.
Upvotes: 2