0

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

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

这是一个示例 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>
4

2 回答 2

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()来更改范围,以便 Angular 运行摘要

DEMO

于 2013-11-09T23:06:31.670 回答
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;
    }
}
于 2015-06-05T15:22:08.423 回答