已编辑:
这是它的工作原理(仍然很长且详尽的解释):
- 创建一个允许您定位触发器元素的自定义指令。
- 创建一个自定义指令,添加到正文中,并在单击时找到触发元素并触发自定义事件。
创建一个自定义指令来定位触发器元素:
您需要从打开弹出框的元素中触发自定义事件处理程序(在演示中这是按钮)。挑战在于弹出框作为同级元素附加到该元素,我始终认为当您遍历 DOM 并期望它具有特定结构时,事情有更大的破坏潜力。有几种方法可以定位触发元素,但我的方法是在单击元素时为元素添加一个唯一的类名(我选择“触发”)。在这种情况下,一次只能打开一个弹出框,因此使用类名是安全的,但您可以根据自己的喜好进行修改。
自定义指令
app.directive('popoverElem', function(){
return{
link: function(scope, element, attrs) {
element.on('click', function(){
element.addClass('trigger');
});
}
}
});
应用于按钮
<button popover-template="dynamicPopover.templateUrl" popover-title="{{dynamicPopover.title}}" class="btn btn-default" popover-elem>Popover With Template</button>
为文档正文(或任何其他元素)创建自定义指令以触发弹出框关闭:
最后一部分是创建一个自定义指令,该指令将定位触发元素并触发自定义事件以在单击应用它的元素时关闭弹出框。当然,您必须从“触发器”元素中排除初始点击事件,以及您想要在弹出框内部与之交互的任何元素。因此,我添加了一个名为 exclude-class 的属性,以便您可以定义一个类,您可以将其添加到应忽略点击事件的元素(不会导致弹出框关闭)。
为了清理,当事件处理程序被触发时,我们删除添加到触发器元素的触发器类。
app.directive('popoverClose', function($timeout){
return{
scope: {
excludeClass: '@'
},
link: function(scope, element, attrs) {
var trigger = document.getElementsByClassName('trigger');
function closeTrigger(i) {
$timeout(function(){
angular.element(trigger[0]).triggerHandler('click').removeClass('trigger');
});
}
element.on('click', function(event){
var etarget = angular.element(event.target);
var tlength = trigger.length;
if(!etarget.hasClass('trigger') && !etarget.hasClass(scope.excludeClass)) {
for(var i=0; i<tlength; i++) {
closeTrigger(i)
}
}
});
}
};
});
我将它添加到 body 标记中,以便整个页面* 充当弹出框的可关闭背景:
<body popover-close exclude-class="exclude">
而且,我在弹出框的输入中添加了排除类:
<input type="text" ng-model="dynamicPopover.title" class="form-control exclude">
所以,有一些调整和陷阱,但我会留给你:
- 您应该在 popover-close 指令的链接函数中设置一个默认排除类,以防未定义。
- 您需要注意 popover-close 指令是元素绑定的,因此如果您删除我在 html 和 body 元素上设置的样式以赋予它们 100% 的高度,您的视口中可能会出现“死区”,如果你的内容没有填满它。
在 Chrome、Firefox 和 Safari 中测试。