Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disabling ngClick event handling in a custom directive

Here is a directive in which I'm attempting to disable a link based on a model value:

app.directive('disableable', function($parse){
    return {
        restrict: 'C',
        require: '?ngClick',
        link: function (scope, elem, attrs, ngClick) {
            if (attrs.disable){
                var disable = $parse(attrs.disable);

                elem.bind('click', function (e) {
                    if (disable(scope)){
                        e.preventDefault();
                        return false;
                    }

                    return true;
                });

                scope.$watch(disable, function (val) {
                    if (val){
                        elem.addClass('disabled');
                        elem.css('cursor', 'default');
                    }
                    else {
                        elem.removeClass('disabled');
                        elem.css('cursor', 'pointer');
                    }
                });
             }
         }
     };
});

I want to be able to disable all link actions, regardless of whether they use simple hrefs or ngClick actions. Hrefs work fine because of the preventDefault call, but I can't figure out how to dig into the ngClick and prevent it from firing. The bind I'm doing on the click event isn't working because it seems ngClick is binding its own handler that I have no control over. Is there anything I can do?

jsFiddle: http://jsfiddle.net/KQQD2/2/

like image 473
mfelix Avatar asked Jul 23 '13 20:07

mfelix


People also ask

What is restrict option in directive?

Note: When you create a directive, it is restricted to attribute and elements only by default. In order to create directives that are triggered by class name, you need to use the restrict option. The restrict option is typically set to: 'A' - only matches attribute name. 'E' - only matches element name.

Which AngularJS directive is used to hide or show an HTML element ng showhide ng showhide ng show ng-hide?

ng-hide Directive: The ng-hide Directive in AngluarJS is used to show or hide the specified HTML element. If the expression given in the ng-hide attribute is true than the HTML elements hide. ng-hide is also a predefined CSS class in AngularJS, and sets the element's display to none.

What is disabled in Angular?

Definition and Usage. The ng-disabled directive sets the disabled attribute of a form field (input, select, or textarea). The form field will be disabled if the expression inside the ng-disabled attribute returns true. The ng-disabled directive is necessary to be able to shift the value between true and false .

What is attrs in AngularJS?

Using attrs you are able to access the attributes defined in your html tag like <fm-rating ng-model="$parent.restaurant.price" symbol="$" readonly="true"> So in this case you will have access to the symbol and readonly attributes.


2 Answers

Use event.stopImmediatePropagation.

From MDN:

If several listeners are attached to the same element for the same event type, they are called in order in which they have been added. If during one such call, event.stopImmediatePropagation() is called, no remaining listeners will be called.

...
elem.bind('click', function (e) {
  if (disable(scope)){
    e.stopImmediatePropagation();
    return false;
  }

  return true;
});
...

WORKING FIDDLE

like image 161
Stewie Avatar answered Sep 24 '22 12:09

Stewie


You could do simply change your ng-click to disableIt || tellAboutIt() and it'll work as-is. e.g

<a class="disableable" target="_blank" ng-click="disableIt || tellAboutIt()">
           ngClick disableable link</a>

Full code:

HTML (i've removed the 'disabled' attributes because they're useless as they don't work on anchor tags):

<div ng-app="app" ng-controller="appCtrl">
    <a class="disableable" target="_blank" ng-click="disableIt || tellAboutIt()">
       ngClick disableable link</a>
    <br/><br/>
    <a class="disableable" target="_blank" href="http://google.com">
       href disableable link</a>
    <br/><br/>
    <input type="checkbox" ng-model="disableIt" /> Disable links
</div>

Angular (I've made your directive more compact):

app.directive('disableable', function($parse){
    return {
        restrict: 'C',
        link: function (scope, elem, attrs) {
            scope.$watch('disableIt', function (val) {
                if (val) {
                    elem.addClass('disabled');
                    elem.css('cursor', 'default');
                    elem.bind('click', function(e) {
                        e.preventDefault();
                    });
                }
                else {
                    elem.removeClass('disabled');
                    elem.css('cursor', 'pointer');
                    if (typeof elem.attr('ng-click') === 'undefined')
                       elem.unbind('click');
                }
            });
        }
    };
});

JSFiddle: http://jsfiddle.net/KQQD2/4/


Alternatively, you could check $scope.disableIt is false before running the code inside tellAboutIt(). e.g.:

$scope.tellAboutIt = function(){
    if ($scope.disableIt === false) {
        $window.alert('ngClick fired. This alert should not show when disabled.');
    }
};
like image 32
mnsr Avatar answered Sep 22 '22 12:09

mnsr