所以我在 AngularJS 中创建了一个切换(下拉)菜单的指令。我将该指令用于页面内的多个项目,但有一个小问题。当一项打开并单击另一项时,我希望关闭前一项。 event.preventDefault 和 event.stopPropagation 停止前一项的事件并且不关闭它。有想法该怎么解决这个吗?有没有办法只停止范围内的事件?
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;
}
});
}
};
这是一个 fiddle :http://jsfiddle.net/JknUJ/5/ 按钮打开内容,在 div 外部单击时内容应关闭。但当单击按钮 2 时,内容 1 不会关闭。
最佳答案
基本思想是您需要在所有下拉子菜单之间共享状态,因此当其中一个下拉子菜单显示时,所有其他下拉子菜单都会隐藏。存储状态(例如打开或关闭)的最简单方法是...... CSS 类!
我们将创建一对指令 - 一个用于菜单,另一个用于 sumbenu。它比 div
更具表现力。
这是外部标记。
<menu>
<submenu data-caption="Button 1">
Content 1
</submenu>
<submenu data-caption="Button 2">
Content 2
</submenu>
</menu>
看看它的可读性如何!对指令表示感谢:
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 元素(restrict : "E"
)。 submenu
需要嵌套在 menu
中(require : "^menu"
),这允许我们将菜单 Controller 注入(inject)到 submenu
的链接功能。 transclude
和 replace
控制原始标记在编译后的 HTML 输出中的位置(replace=true
表示原始标记将被编译后的、 >transclude
将原始标记的一部分插入到编译的输出中)。
完成此操作后,我们只需对菜单说关闭所有子菜单!并且菜单会迭代子菜单,强制它们关闭。
我们正在 addSubmenu
函数中将子项添加到 menu
Controller 。它在submenu
的链接函数中调用,因此子菜单的每个编译实例都将其自身添加到menu
中。现在,关闭所有子菜单
就像迭代所有子菜单一样简单,这是通过menu
Controller 中的closeAllSubmenus
完成的。
Here是一个完整的 Plunker 可以玩。
关于events - AngularJS 指令切换菜单防止其他指令的默认设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18171901/