用于AngularJS的下拉切换,在其他位置单击时关闭

时间:2013-11-08 23:53:30

标签: angularjs twitter-bootstrap angular-ui-bootstrap

在AngularJS中实现一个使用ng-show显示或隐藏菜单的简单下拉指令是微不足道的。如果用户在打开菜单后单击屏幕中的其他位置,我还想关闭菜单。最简单的正确方法是什么?我曾尝试使用$ document.bind和$ document.unbind从文档中解除绑定,但它似乎没有按预期工作,我无法工作应该如何工作,因为范围问题。

我知道ui-bootstrap有一个类似的指令(dropdownToggle),我已经挖掘了它的源代码,但它看起来要复杂得多,并且引入了对旧版本bootstrap的依赖。

这是example plunker(在其他地方点击时不关闭菜单)。

代码:

<!DOCTYPE html>
<html  ng-app="plunker" >
  <head>
    <link data-require="bootstrap-css@3.0.0" data-semver="3.0.0" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" />
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js"></script>
    <script src="example.js"></script>
    <link href="///netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" />
  </head>

  <body>
    <div  ng-app="dropdown">
      <div menu-status-widget></div>
    </div>
  </body>

</html>

2 个答案:

答案 0 :(得分:2)

以下是使用ng-click处理情况的方法。您需要将$event参数传递到ng-click函数中,以便调用$event.stopPropagation()

ng-click似乎没有像jQuery处理程序那样做出反应。它似乎实际上在所有代码运行后触发事件,因此这会导致您刚添加的$document处理程序实际触发。

<div ng-click="buttonAction($event)" >
    scope.buttonAction = function($event) {
              $event.stopPropagation()
                if (!scope.showMenu) {
                    var closeMe = function(scope) { 
                      scope.showMenu = false;
                      $document.unbind('click', this);
                    };
                    $document.bind('click', function(event) {
                    scope.$apply(function(){
                       closeMe(scope)
                    })
                      }); 
                    scope.showMenu = true;
                } else {
                    scope.showMenu = false;
                } 
            };

在我看来,忘记ng-click并使用element.bind更为简单。无论哪种方式,您仍然必须使用scope.$apply()来更改范围,以便角度运行摘要

DEMO

答案 1 :(得分:1)

您可以修饰指令。

通过这种方式,您无需触摸原始代码即可保留原始行为。

您可以在下拉列表中放置关闭按钮

<强> HTML

<div class="dropdown-menu keep-dropdown-open-on-click" role="menu">
    <i class="icon-close close-dropdown-on-click"></i>
</div>

<强> JS

angular.module('app').config(uiDropdownMenuDecorate);
uiDropdownMenuDecorate.$inject = ['$provide'];
function uiDropdownMenuDecorate($provide) {

    $provide.decorator('dropdownMenuDirective', uiDropdownMenuDecorator);

    uiDropdownMenuDecorator.$inject = ['$delegate'];

    function uiDropdownMenuDecorator($delegate) {

        var directive = $delegate[0];
        var link = directive.link;

        directive.compile = function () {
            return function (scope, elem, attrs, ctrl) {
                link.apply(this, [scope, elem, attrs, ctrl]);
                elem.click(function (e) {
                    if (elem.hasClass('keep-dropdown-open-on-click') && !angular.element(e.target).hasClass('close-dropdown-on-click')) {
                        e.stopPropagation();
                    }
                });
            };
        };

        return $delegate;
    }
}