我有一个小的下拉指令,我应用于nav元素。如果用户通过设置$scope.menu.visible = false
点击导航元素之外的任何位置,我想关闭下拉列表。
从Angular指令中检查body元素上的click或keypress的最Angular方法是什么?
我目前的指令如下:
angular.module('dropdowns', [])
.directive('dropdown', function () {
return {
scope: true,
link: function (scope, element) {
var body = angular.element('body');
var clickOutside = function (e) {
var target = angular.element(e.target);
if (!$.contains(element, target)) {
scope.menu.visible = false;
}
}
body.on('click', clickOutside);
// body.on('keyup', scope.escapeKey);
},
controller: function($scope) {
$scope.menu = {visible: false};
$scope.hide = function () {
$scope.menu.visible = false;
};
$scope.show = function () {
scope.menu.visible = true;
};
$scope.toggle = function (e) {
$scope.menu.visible = !$scope.menu.visible;
};
$scope.escapeKey = function (e) {
if (e.which === 27) {
$scope.hide();
}
};
}
};
});
使用以下模板片段设置下拉列表:
<nav dropdown>
<a ng-click="toggle()">Menu</a>
<ul ng-show="menu.visible">
...
</ul>
</nav>
答案 0 :(得分:2)
最角度的方式: 将其添加到指令中。示例:将click-events属性添加到&#39; body&#39;标签 类似的东西:
angular.module('directive_name', []).directive('clickEvents', [
'$rootScope',
'$document',
function($rootScope, $document) {
return {
link: function() {
$document.bind('click', function(event) {
$rootScope.$broadcast('click', event);
});
}
};
}
]);
module.directive('directive_name', [
function() {
return {
link: function(scope, element, attributes) {
scope.$on('click', function(onEvent, clickEvent) {
scope.clicked = true;
});
}
};
}
]);
答案 1 :(得分:1)
<body ng-click="yourFunction()">
似乎是明显的选择。但是,请确保ng-app
指令在<html>
上,以便在应用中包含<body>
。
答案 2 :(得分:1)
不知道&#34;最角度的方式&#34;,但也许最容易。 假设你的模板中有这样的东西。
<ul class="dropdown-menu keep_open">
<li>....
然后在您的指令link
或controller
中,只需添加以下功能
/* forces dropdown to remain open until clicked outside the control */
$('.keep_open').click(function(event){
event.stopPropagation();
});
此处相关的plunker http://plnkr.co/edit/tj2ljc
<小时/>
答案 3 :(得分:1)
你的实现看起来很不错,但我真的会研究下拉列表的Bootstrap实现。
https://github.com/angular-ui/bootstrap/blob/master/src/dropdown/dropdown.js
答案 4 :(得分:1)
您需要做的就是在下拉指令元素级别停止事件传播。轮到它的身体元素将处理进入它的点击事件。以下是您的指令的链接功能:
link: function(scope, element) {
var body = angular.element('body');
body.on('click', function(e) {
scope.$apply(function() {
scope.menu.visible = false;
});
});
element.on('click', function(e) {
e.stopPropagation();
});
// body.on('keyup', scope.escapeKey);
},
答案 5 :(得分:0)
我会分享我的最终代码,以防它对其他任何人有用。有一些很好的提示,例如从rootScope广播并使用stopPropagation。我最终得到了类似的东西。当单击下拉列表中未包含的任何元素或按下转义键时,它将关闭。
我最终在闭包中保留了对body的引用,因此每个下拉列表都保留了它自己的引用,它仍然需要一个select,但是变得自包含,这是一个奖励。
angular.module('dropdowns', [])
.directive('dropdown', function () {
return {
scope: true,
link: function (scope, element) {
scope.menu = {
visible: false
};
scope.hide = function () {
scope.menu.visible = false;
};
scope.show = function () {
scope.menu.visible = true;
};
scope.toggle = function (e) {
scope.menu.visible = !scope.menu.visible;
};
var escapeKey = function (e) {
if (e.which === 27) {
scope.hide();
scope.$apply();
}
};
var clickOutside = function (e) {
if (!$.contains(element[0], e.target)) {
scope.hide();
scope.$apply();
}
}
var body = angular.element('body');
body.on('click', clickOutside);
body.on('keyup', escapeKey);
}
};
});