Jeremi Stadler
Jeremi Stadler

Reputation: 2637

AngularJS Directive scope gets overwriten

Task

I want a directive that calls a function when clicking outside of the element. The use case it to have menu's opening onclick and closing when clicking outside of them.

Problem

The directive binds a onlick to the window to ckeck for clicks outside of the element but the onclick function gets the last scope, not the "right" scope

Plunkr

http://plnkr.co/edit/ePKMMsbe9HYikY9XQ1u3?p=preview

Simplified Directive:

app.directive('clickanywherebuthere', ['$document', '$timeout', function($document, $timeout) {
return {
    link: function postLink(scope, element, attrs) {
        onClick = function(event) {
            var isChild = element.has(event.target).length > 0;
            var isSelf = element[0] == event.target;
            var isInside = isChild || isSelf;
            if (!isInside)
                scope.$apply(attrs.clickanywherebuthere)
        }

        scope.$watch(attrs.isActive, function(newValue, oldValue) {
            if (newValue !== oldValue && newValue == true) {
                $timeout(function() { $document.bind('click', onClick) })
            }
            else if (newValue !== oldValue && newValue == false) {
                $document.unbind('click', onClick);
            }
        });
    }
};
}])

Upvotes: 1

Views: 83

Answers (2)

Walter Brand
Walter Brand

Reputation: 689

Perhaps it is better not to listen for clicks outside a directive via the link function of the directive. I suggest you add a global listener for clicks on the page that broadcast the name of the element that is clicked on (of whatever you prefer) and make the directive listen for these events with scope.$on('name-of-event');

and in the run phase of your app, you add the click listener that broadcast the value of the clicked element

angular.module('test').run(function($rootScope){
  $(document).click(function(event){
    $rootScope.$broadcast('clickanywhere',event.target.nodeName)  
    })
  })

Upvotes: 0

ReedD
ReedD

Reputation: 997

The problem is that onClick only gets created the first time your directive is called and it's bound to the first button's scope. You need to add "var" in front of "onClick" to make it work properly. I modified your plnkr below:

http://plnkr.co/edit/0TrIM6d1Y6mneYgMcCjN?p=preview

Upvotes: 1

Related Questions