AngularJS指令切换菜单preventing默认为其他指令 [英] AngularJS directive toggle menu preventing default for other directive

查看:132
本文介绍了AngularJS指令切换菜单preventing默认为其他指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

于是我做了一个指令,用于切换(下拉)菜单中的AngularJS。我使用的页面中的多个项目的指示,但我有一个小问题。当一个项目是开放的,我点击另外一个我想要的previous一个关闭。本次活动。preventDefault和event.stopPropagation停止事件为previous项目并不会关闭它。关于如何解决这个任何想法?有没有一种办法或许只有范围内停止活动?

So I made a directive for a toggle (drop down) menu in AngularJS. I used the directive for multiple items within the page but I have a small problem. When one item is open and I click another one I want the previous one to close. The event.preventDefault and event.stopPropagation stops the event for the previous item and doesn't close it. Any ideas on how to fix this? Is there a way to perhaps only stop the event within the scope?

app.directive('toggleMenu', function ($document) {
    return {
        restrict: 'CA',
        link: function (scope, element, attrs) {
            var opened = false;
            var button = (attrs.menuButton ? angular.element(document.getElementById(attrs.menuButton)) : element.parent());
            var closeButton = (attrs.closeButton ? angular.element(document.getElementById(attrs.closeButton)) : false);

            var toggleMenu = function(){
                (opened ? element.fadeOut('fast') : element.fadeIn('fast'));
            };

            button.bind('click', function(event){
                event.preventDefault();
                event.stopPropagation();
                toggleMenu();
                opened = ! opened;
            });

            element.bind('click', function(event){
                if(attrs.stayOpen && event.target != closeButton[0]){
                    event.preventDefault();
                    event.stopPropagation();
                }
            });

            $document.bind('click', function(){
                if(opened){
                    toggleMenu();
                    opened = false;
                }
            });


        }
    };

这是一个小提琴: http://jsfiddle.net/JknUJ/5/
按钮打开的内容,当外面的div点击内容应该关闭。当不过按钮2点击内容1不会关闭。

And here's a Fiddle: http://jsfiddle.net/JknUJ/5/ Button opens content and content should close when clicked outside the div. When clicked on button 2 however content 1 doesn't close.

推荐答案

基本想法是,你需要将所有的下拉子菜单之间共享的状态,所以当显示其中之一,所有其他被隐藏。存储状态(如打开或关闭)的simpliest方式是... CSS类!

Basic idea is that you need to share the state between all your dropdown submenus, so when one of them is shown, all others are hidden. The simpliest way of storing state (such as opened or closed) are... CSS classes!

我们将创建一个对指令 - 一个菜单,另一个用于sumbenu。这是更前pressive刚 DIV 秒。

We'll create a pair of directives - one for menu, and another for sumbenu. It is more expressive that just divs.

下面是出标记。

<menu>
  <submenu data-caption="Button 1">
    Content 1
  </submenu>
  <submenu data-caption="Button 2">
    Content 2
  </submenu>
</menu>

看看是怎么读呢!说感谢指令:

Look how readable is it! Say thanks to directives:

plunker.directive("menu", function(){
    return {
        restrict : "E",
        scope : {},
        transclude : true,
        replace : true,
        template : "<div class='menu' data-ng-transclude></div>",
        controller : function ($scope, $element, $attrs, $transclude){
            $scope.submenus = [];

            this.addSubmenu = function (submenu) {
                $scope.submenus.push(submenu);
            }

            this.closeAllSubmenus = function (doNotTouch){
                angular.forEach($scope.submenus, function(submenu){
                    if(submenu != doNotTouch){
                        submenu.close();    
                    }
                })
            }
        }
    }
});

plunker.directive("submenu", function(){
    return {
        restrict : "E",
        require : "^menu",
        scope : {
            caption : "@"
        },
        transclude : true,
        replace : true,
        template : "<div class='submenu'><label>{{caption}}</label><div class='submenu-content' data-ng-transclude></div></div>",
        link : function ($scope, $iElement, $iAttrs, menuController) {
            menuController.addSubmenu($scope);

            $iElement.bind("click", function(event){
                menuController.closeAllSubmenus($scope);
                $iElement.toggleClass("active");
            });

            $scope.close = function (){
                $iElement.removeClass("active");
            }
        }
    }
});

看塔尔我们限制他们HTML元素(限制:E)。 子菜单要求嵌套在菜单要求:^菜单中的),这让我们注入菜单控制器子菜单的链接功能。 transclude 替换控制在编译的HTML输出(原来标记的位置替换= true的意味着原来的标记将被替换编译, transclude 插入原始标记的部分编译输出)。

Look thar we restricted them to HTML elements (restrict : "E"). submenu requires to be nested in menu (require : "^menu"), this allows us to inject menu controller to submenu's link function. transclude and replace controls the position of original markup in compiled HTML output (replace=true means that original markup will be replaced with compiled, transclude inserts parts of original markup to compiled output).

当我们与这个工作,我们只说菜单的关闭所有子菜单!的和菜单迭代子,迫使他们关闭。

When we've done with this, we just say to menu close all your child menus! and menu iterates over submenus, forcing them to close.

我们正在增加孩子的到菜单控制器 addSubmenu 功能。这就是所谓的子菜单 s链路功能,从而子菜单的每个实例编制增加了自身菜单。现在,关闭所有子菜单是循环访问所有的孩子一样简单,这是由 closeAllSubmenus 在<$ C $完成C>菜单控制器。

We are adding childs to menu controller in addSubmenu function. It is called in submenus link function, thus every compiled instance of submenu adds itself to menu. Now, closing all submenus is as easy as iterating over all children, this is done by closeAllSubmenus in menu controller.

这里是一个完整的Plunker一起玩。

Here is a full Plunker to play with.

这篇关于AngularJS指令切换菜单preventing默认为其他指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆