Angularjs 测试指令中单击主体的角度最大的方法是什么?
我有一个应用于导航元素的小下拉指令。如果用户通过设置Angularjs 测试指令中单击主体的角度最大的方法是什么?,angularjs,angularjs-directive,Angularjs,Angularjs Directive,我有一个应用于导航元素的小下拉指令。如果用户通过设置$scope.menu.visible=false单击导航元素之外的任何位置,我希望关闭下拉列表 在Angular指令中检查body元素上的单击或按键的角度最大的方法是什么 我目前的指令如下所示: angular.module('dropdowns', []) .directive('dropdown', function () { return { scope: true, link: function (
$scope.menu.visible=false
单击导航元素之外的任何位置,我希望关闭下拉列表
在Angular指令中检查body元素上的单击或按键的角度最大的方法是什么
我目前的指令如下所示:
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>
菜单
...
似乎是显而易见的选择。但是,请确保您的ng应用程序
指令已打开
,以便将
包含在应用程序中。最有角度的方式:
将其添加到指令中。示例:将单击事件属性添加到“body”标记
比如:
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;
});
}
};
}
]);
不知道“最有棱角的方式”,但可能是最简单的。
假设您的模板中有类似的内容
<ul class="dropdown-menu keep_open">
<li>....
我是相关的普朗克
您的实现看起来相当不错,但我真的要研究一下下拉菜单的引导实现
在您的案例中,您需要做的就是在下拉指令元素级别停止事件传播。Body元素将处理指向它的单击事件。下面是您的指令的链接功能的外观:
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);
},
演示:我将分享我的最终代码,以防它对其他人有用。这里有一些很好的提示,例如从rootScope广播和使用stopPropagation。我的结局是这样的。单击下拉列表中未包含的任何元素或按escape键时,它将关闭 我最终在闭包中保留了对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);
}
};
});
这可以正常工作,但无法访问下拉菜单$scope,假设页面上有多个下拉菜单。在这种情况下,您应该稍微修改一下指令。发布其代码。您好@dfsq,代码已发布。如您所见,我在这里使用jQuery来选择链接函数中的body元素,违反了“don't select,direct”的精神。您如何在HTML中使用您的指令?如何打开下拉列表?@dfsq-好问题,我已经发布了模板。这是标准的东西。最初我的指令中有更多内容,但当涉及到进行更改时,我发现这限制了我的选择。看看理想方法的简单程度。StopRoppagation的缺点是,如果我有多个下拉列表(我有),并且我单击了第二个,第一个将保持打开状态。不,其他的将关闭。我编辑了我的答案,请参阅相关的plunker:)哦,嘿,这很好,那么该指令只需要知道$rootScope,这是一个简单的DI。当然,试试看,你会发现:)看起来不错,但就我个人而言,如果我不必污染$rootScope,并且节省使用事件。它很好,但在多个nav下拉列表中失败,即,单击一个导航元素不会关闭页面其他位置的其他导航元素。
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);
},
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);
}
};
});