2

My button instantiation is here:

<button ng-hide="todo === 'add'" confirm-click ng-click="delete()">Delete</button>  

My directive code is here:

(function(app) {
    app.directive('confirmClick', function(){
        return {
            restrict: 'A',
            priority: 1,
            terminal: true,
            link: function(scope, element, attr) {
                var msg = attr.confirmationNeeded || "Really Delete?";
                var clickAction = attr.ngClick;
                element.bind('click', function() {
                    if(window.confirm(msg)){
                        scope.$apply(clickAction);
                    }
                });
            }
        }; 
    });
}(angular.module('case1')));

If I remove the directive from the button ng-hide works, if I include the directive it no longer works. I would assume that the $scope.todo variable is outside of scope when I include the directive, but I wonder how I can go about fixing this?

PSL
  • 123,204
  • 21
  • 253
  • 243
mcraenich
  • 745
  • 1
  • 14
  • 38

2 Answers2

3

Key here is terminal:true which causes execution of ng-hide not to happen, it is not the priority alone that is causing the behavior that you are seeing.

terminal - If set to true then the current priority will be the last set of directives which will execute (any directives at the current priority will still execute as the order of execution on same priority is undefined).


Let your directive execute after ng-hide which has a priority 0. Since you have terminal option on your directive it will skip the execution of ng-hide as your directive's priority is 1 and ng-hide has lower.

Try: -

return {
        restrict: 'A',
        terminal: true,
        link: function(scope, element, attr) {
            var msg = attr.confirmationNeeded || "Really Delete?";
            var clickAction = attr.ngClick;
            element.bind('click', function() {
                if(window.confirm(msg)){
                    scope.$apply(clickAction);
                }
            });
    }

Demo

Or just remove terminal option from your directive which when present tells Angular to skip all directives on that element that comes after it (lower priority), unless you really need it.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
PSL
  • 123,204
  • 21
  • 253
  • 243
2

It is because of the priority: 1 property in your directive definition.

From the docs:

priority

When there are multiple directives defined on a single DOM element, sometimes it is necessary to specify the order in which the directives are applied. The priority is used to sort the directives before their compile functions get called. Priority is defined as a number. Directives with greater numerical priority are compiled first. Pre-link functions are also run in priority order, but post-link functions are run in reverse order. The order of directives with the same priority is undefined. The default priority is 0.

From source for ngHide, you can see it has no priority level set, so it would default to 0. When you are setting your directive's priority to 1, you are forcing Angular to compile it first.

Either set the priority to 0, or omit the property and let it default to 0.

Community
  • 1
  • 1
Michael Bromley
  • 4,792
  • 4
  • 35
  • 57
  • It is not really the priority, it is the terminal option that is key here. If you do not have terminal option you will see it running fine.. I have quoted it in my answer. Priority will just say when they must execute, so all the directives will execute after all, unless you say your directive is terminal and dont run anything beyond my directives priority – PSL Sep 21 '14 at 16:52
  • Yeah, I should've been explicit with that. Anyway, he has to choose an answer and I think yours is the most complete for that reason. – Michael Bromley Sep 21 '14 at 16:54