在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>
答案 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;
}
}