侦听在页面上多次使用的单击外部指令

时间:2014-05-09 09:20:33

标签: javascript angularjs

我有一个自定义指令,其内部有一个弹出菜单,当我点击指令中的一个按钮时应显示该指令,只要我在指令外单击它就应该关闭。

我将指令用于列表中的多个项目,因此页面上总会有多个此指令。

现在我有一些代码正在侦听文档上的点击。我已将此代码移动到我的控制器,因为它根据页面上的指令数量进行了x次评估。

我能做些什么来保持指令中的所有代码?

// BOTTOM OF MY CONTROLLER //

// function to be called when clicking outside the directive/menu
onDocumentClick = function(event){
// if not clicked on an .popup-btn then remove all classnames from popup-menu
activeNodes = document.getElementsByClassName("popup-menu active");
if(activeNodes.length >= 1){
    clicked_el = angular.element(event.target);
    if(!/^popup-btn|popup-menu/.test(clicked_el[0].className)){
        for (var i = 0; i < activeNodes.length; i++){
            activeNodes[i].className = "popup-menu";
            console.log(activeNodes[i]);
        }
    }
}
};

$document.on('click', onDocumentClick);
}]);

// END OF CONTROLLER //

//Directive
mealplan.directive('recipe', ['$document', function($document) {
return {
    restrict: 'AE',
    scope: {
        item: '=recipe' 
    },
    link: function(scope, elem, attrs) {
        // toggle the recipe menu
        scope.toggleMenu = function() {
            console.log("toggle menu");
            // loop throug all menus and reset their class names
            activeNodes = document.getElementsByClassName("popup-menu active");
            if(activeNodes.length >= 1){
                for (var i = 0; i < activeNodes.length; i++){
                    activeNodes[i].className = "popup-menu";
                    console.log(activeNodes[i]);
                }
            }
            // set the current 
            current = elem[0].getElementsByClassName("popup-menu")[0];
            current.className = "popup-menu active";
            console.log(current);
        };

        // initializes the states
        scope.init = function() {
            //scope.currentMenu = null;
        };

        scope.init();

    },
    templateUrl: 's/recipes/js/popupMenu-directive.html'
};
}]);

2 个答案:

答案 0 :(得分:1)

在返回options对象之前在指令中执行的代码只执行一次。

来自Angular-UI documentation

myApp.directive('uiJq', function InjectingFunction(){

    // === InjectingFunction === //
    // Logic is executed 0 or 1 times per app (depending on if directive is used).
    // Useful for bootstrap and global configuration
    // Do the binding here
    return {
        compile: function CompilingFunction($templateElement, $templateAttributes) {

            // Logic is executed once (1) for every instance of ui-jq

            return function LinkingFunction($scope, $linkElement, $linkAttributes) {
                // Logic is executed once (1) for every RENDERED instance.
            };
        }
    };
})

您可以在声明指令后绑定事件处理程序,并且只执行一次。

答案 1 :(得分:0)

不是很优雅,但您可以使用.off删除绑定(如果已存在),然后设置.on事件。

$document.off('click.some-namespace');
$document.on('click.some-namespace', function() { ... });

使用事件命名空间保持其他任何点击事件不变。这样,无论指令的使用次数如何,事件都应该绑定一次。