ng-click still fires when div is (ng)disabled

All we need is an easy explanation of the problem, so here it is.

Problem is that ng-click works on so event if cancelTicket === false it still fires ng-click. How can I stop that?

<div class="btn-block save-changes padding-10" ng-class="{'gray':cancelTicket===false,'secondary-button':cancelTicket===true}" ng-click="CancelTicket(ticketPin)" ng-disabled="cancelTicket===false" style="display: table;">
    <div class="button-container padding3" ng-class="{'pointer':cancelTicket===true}">
        <button-spinner promise="cancelPromise"></button-spinner>
        <div style="display: inline-block !important;"> @Translator.Translate("CANCEL") </div>
    </div>
</div>

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Event is triggered even if the div is disabled.

You can avoid this by using lazy evaluation of expressions like isDisabled || action() so action would not be called if isDisabled is true.

In your case it will be:

ng-click="cancelTicket === false || CancelTicket(ticketPin)"

Method 2

You should change DIV tag to Button Tag.
It works for me.

Method 3

You can disable click events when an element with ng-click is disabled.

jQuery:

$('*[ng-click]').on('click',function(event) {
     var $el = $(event.target);
     if($el.attr('disabled')) {
        event.stopPropagation();
     }
});

Doing this on all DOM elements could produce unwanted results. Also, you will need to run the above on any new HTML updated on the DOM.

Instead, we can modify just buttons to work as expected.

Angular:

angular.module('app').directive('button',function() {
     return {
          restrict: 'E',
          link: function(scope,el) {
              var $el = angular.element(el);
              $el.bind('click', function(event) {
                  if($el.attr('disabled')) {
                      event.stopImmediatePropagation();
                  }
              });
          }
     }
});

I would not do the above on div elements as it would be to heavy. Instead, modify your approach so that button elements are only used for clickable interactions. You can then style them to look like other div elements.

Method 4

<a class="btn btn-danger btn-xs" ng-click="vm.handleRemove(device)" ng-disabled="status === 1">Delete</a>

Change a tag to button tag then OK

<button class="btn btn-danger btn-xs" ng-click="vm.handleRemove(device)" ng-disabled="status === 1">Delete</button>

Method 5

My solution has been to use an html directive with an attribute used instead of ng-click, so that

<html-tag-directive new-click="ctrl.functionToCall()" disabled="ctrl.disabled" >

and the directive defined as follow:

1) template:

<button type="button" 
   ng-disabled="disabled" ng-click="onClick()">
</button>

2) controller:

angular.module('module')
.directive('htmlTagDirective',function() {
    return {
        restrict:'E',
        templateUrl:'template.html',
        scope:{
            disabled:'=',
            click: '&'
        },
        link:function(scope,element){

            scope.onClick = function() {
                if (!(scope.disabled)) {
                    scope.newClick();
                }
            };

        }
    };
});

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply