Preventing multiple clicks in angularjs

When I want to delete an entry from my page, I need to show a confirmation before deleting. For this I used anchor and ng-click='delete()'

for deleting such a line. Here the user can click on the anchor multiple times. This is a serious issue because the confirmation popup appears multiple times. My example is a sample. In my project, I ran into problems like this. I want to prevent multiple click to zoom ng-click

.

+3


source to share


4 answers


If we override the ngClick directive, we can protect multiple clicks.



app.config(['$provide', function ($provide) {
        $provide.decorator('ngClickDirective',['$delegate','$timeout', function ($delegate,$timeout) {
            var original = $delegate[0].compile;
                  var delay = 500;
            $delegate[0].compile = function (element, attrs, transclude) {

                var disabled = false;
                function onClick(evt) {
                    if (disabled) {
                        evt.preventDefault();
                        evt.stopImmediatePropagation();
                    } else {
                        disabled = true;
                        $timeout(function () { disabled = false; }, delay, false);
                    }
                }
                //   scope.$on('$destroy', function () { iElement.off('click', onClick); });
                element.on('click', onClick);

                return original(element, attrs, transclude);
            };
            return $delegate;
        }]);
    }]);

      

+8


source


for simplicity ng-click = "your_function ()"

`

your_function(){
if(this.allowClick){
            return false;
        }
this.allowClick = true;
// do your func her
//end function
this.allowClick = false;
}

      



`

hope this help!

+1


source


Why not just add a flag that means the function was, and it works / works. You can release the working / working state after completing or canceling the task. Also ... (see self.isWorking

or vm.isWorkng

linked to directive ng-disabled

at link). In the example below, the user can try spam by clicking the Delete button and he will not display multiple confirmation fields since after he clicks the link it will be disabled and will only be enabled again when the code releases it. Good for form submissions etc. where you want to prevent spam.

(function() {
  'use strict';
  
  angular.module('myApp',[]);
  
  angular.module('myApp')
    .factory('mySvc', mySvc);
  
  mySvc.$inject = ['$timeout', '$log'];
  function mySvc($timeout, $log) {
    var svc = {
      deleteSomething: deleteSomething
    };
    
    return svc;
    
    function deleteSomething() {
      return $timeout(function() {
        $log.info('Deleting something...');
        return true;
      }, 5000); //pretends the delete will take like 5 seconds
    }    
  }
  
  angular.module('myApp')
    .controller('myCtrl', myCtrl);
  
  myCtrl.$inject = ['$log', 'mySvc'];
  function myCtrl($log, mySvc) {
    var self = this;    
    self.isWorking = false;    
    self.delete = deleteFn;
    
    function deleteFn() {
      self.isWorking = true; //this should disable the link
      if (!confirm('Are you sure? OK to continue, Cancel to cancel')) {
        self.isWorking = false;
        return;
      }
      
      //confirmed...so delete..
      mySvc.deleteSomething()
        .then(function() {
          $log.info('Deleted!');
        })
        .finally(function() {
          self.isWorking = false;
        });
    }
  }  
}());
      

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp" ng-controller="myCtrl as vm">
<a href="#" ng-click="vm.delete()" ng-disabled="vm.isWorking">Delete!!</a>
</div>
      

Run codeHide result


0


source


My approach is to create a custom directive like this

Module.directive("singleClick", ['$parse',
function($parse) {
    return {
        restrict: 'A',
        scope: true,
        compile: function ($element, attr) {
            var fn = $parse(attr.singleClick);
            return function(scope, element) {
                scope.running = false;

                element.on("click", function (event) {
                    scope.$apply(function () {
                        if(!scope.running) {
                            var result = fn(scope, { $event: event });
                            if(!!result && result.finally !== undefined) {
                                scope.running = true;
                                element.addClass('state-waiting');
                                result.finally(function () {
                                    element.removeClass('state-waiting');
                                    scope.running = false;
                                });
                            }
                        }
                    });
                });
            };
        }
    };
}]);

      

it expects the called function to return a promise. It adds the class state-waiting

to the element and adds the variable running

to the scope.

EDIT: Below is an example using https://jsfiddle.net/zsp7m155/

0


source







All Articles