I'm trying to create a multiselect dropdown list with checkbox and filter option. I'm trying to get the list hidden with I click outside but could not figure it out how. Appreciate your help.
我正在尝试创建一个多选择下拉列表与复选框和过滤器选项。我试着把列表隐藏起来,我在外面点了一下,但是我不知道怎么做。感谢你的帮助。
http://plnkr.co/edit/tw0hLz68O8ueWj7uZ78c
http://plnkr.co/edit/tw0hLz68O8ueWj7uZ78c
7 个解决方案
#1
63
Watch out, your solution (the Plunker provided in the question) doesn't close the popups of other boxes when opening a second popup (on a page with multiple selects).
注意,您的解决方案(在问题中提供的插入器)在打开第二个弹出窗口时(在具有多个选择的页面上)不会关闭其他框的弹出窗口。
By clicking on a box to open a new popup the click event will always be stopped. The event will never reach any other opened popup (to close them).
通过单击一个框来打开一个新的弹出窗口,单击事件将始终被停止。事件将永远不会到达任何其他打开的弹出窗口(关闭它们)。
I solved this by removing the event.stopPropagation();
line and matching all child elements of the popup.
我通过删除event.stopPropagation()来解决这个问题;行并匹配弹出窗口的所有子元素。
The popup will only be closed, if the events element doesn't match any child elements of the popup.
只有当事件元素与弹出的任何子元素不匹配时,弹出窗口才会被关闭。
I changed the directive code to the following:
我将指令码改为:
select.html (directive code)
选择。html(指令代码)
link: function(scope, element, attr){
scope.isPopupVisible = false;
scope.toggleSelect = function(){
scope.isPopupVisible = !scope.isPopupVisible;
}
$(document).bind('click', function(event){
var isClickedElementChildOfPopup = element
.find(event.target)
.length > 0;
if (isClickedElementChildOfPopup)
return;
scope.$apply(function(){
scope.isPopupVisible = false;
});
});
}
I forked your plunker and applied the changes:
我给你的活塞分叉并应用了这些变化:
Plunker: Hide popup div on click outside
柱塞:隐藏弹出式div,点击外部
Screenshot:
截图:
#2
43
This is an old post but in case this helps anyone here is a working example of click outside that doesn't rely on anything but angular.
这是一篇老文章,但如果这对任何人都有帮助的话,这是一个点击之外的工作例子,它不依赖于任何东西,除了角度。
module('clickOutside', []).directive('clickOutside', function ($document) {
return {
restrict: 'A',
scope: {
clickOutside: '&'
},
link: function (scope, el, attr) {
$document.on('click', function (e) {
if (el !== e.target && !el[0].contains(e.target)) {
scope.$apply(function () {
scope.$eval(scope.clickOutside);
});
}
});
}
}
});
#3
8
OK I had to call $apply() as the event is happening outside angular world (as per doc).
我必须调用$apply(),因为事件发生在角度世界之外(根据doc)。
element.bind('click', function(event) {
event.stopPropagation();
});
$document.bind('click', function(){
scope.isVisible = false;
scope.$apply();
});
#4
7
I realized it by listening for a global click event like so:
我通过收听这样的全球点击事件实现了这一点:
.directive('globalEvents', ['News', function(News) {
// Used for global events
return function(scope, element) {
// Listens for a mouse click
// Need to close drop down menus
element.bind('click', function(e) {
News.setClick(e.target);
});
}
}])
The event itself is then broadcasted via a News service
然后,活动本身通过新闻服务进行广播
angular.factory('News', ['$rootScope', function($rootScope) {
var news = {};
news.setClick = function( target ) {
this.clickTarget = target;
$rootScope.$broadcast('click');
};
}]);
You can then listen for the broadcast anywhere you need to. Here is an example directive:
然后你可以在任何需要的地方收听广播。这里有一个例子指令:
.directive('dropdown', ['News', function(News) {
// Drop down menu für the logo button
return {
restrict: 'E',
scope: {},
link: function(scope, element) {
var opened = true;
// Toggles the visibility of the drop down menu
scope.toggle = function() {
element.removeClass(opened ? 'closed' : 'opened');
element.addClass(opened ? 'opened' : 'closed');
};
// Listens for the global click event broad-casted by the News service
scope.$on('click', function() {
if (element.find(News.clickTarget.tagName)[0] !== News.clickTarget) {
scope.toggle(false);
}
});
// Init
scope.toggle();
}
}
}])
I hope it helps!
我希望它可以帮助!
#5
4
There is a cool directive called angular-click-outside
. You can use it in your project. It is super simple to use:
有一个很酷的指令叫做angular-click-outside。您可以在项目中使用它。使用起来超级简单:
https://github.com/IamAdamJowett/angular-click-outside
https://github.com/IamAdamJowett/angular-click-outside
#6
3
I was not totally satisfied with the answers provided so I made my own. Improvements:
我对所提供的答案并不完全满意,所以我自己做了。改进:
- More defensive updating of the scope. Will check to see if a apply/digest is already in progress
- 更多的防御性更新的范围。将检查是否已经有应用/摘要正在进行中?
- div will also close when the user presses the escape key
- 当用户按下escape键时,div也会关闭
- window events are unbound when the div is closed (prevents leaks)
- 当div被关闭时,窗口事件被解除绑定(防止泄漏)
-
window events are unbound when the scope is destroyed (prevents leaks)
当范围被破坏时,窗口事件被解除绑定(防止泄漏)
function link(scope, $element, attributes, $window) {
函数链接(范围,$元素,属性,$窗口)
var el = $element[0], $$window = angular.element($window); function onClick(event) { console.log('window clicked'); // might need to polyfill node.contains if (el.contains(event.target)) { console.log('click inside element'); return; } scope.isActive = !scope.isActive; if (!scope.$$phase) { scope.$apply(); } } function onKeyUp(event) { if (event.keyCode !== 27) { return; } console.log('escape pressed'); scope.isActive = false; if (!scope.$$phase) { scope.$apply(); } } function bindCloseHandler() { console.log('binding window click event'); $$window.on('click', onClick); $$window.on('keyup', onKeyUp); } function unbindCloseHandler() { console.log('unbinding window click event'); $$window.off('click', onClick); $$window.off('keyup', onKeyUp); } scope.$watch('isActive', function(newValue, oldValue) { if (newValue) { bindCloseHandler(); } else { unbindCloseHandler(); } }); // prevent leaks - destroy handlers when scope is destroyed scope.$on('$destroy', function() { unbindCloseHandler(); });
}
}
I get $window
directly into the link function. However, you do not need to do this exactly to get $window
.
我得到$window直接进入链接函数。但是,您不需要这样做来获得$window。
function directive($window) {
return {
restrict: 'AE',
link: function(scope, $element, attributes) {
link.call(null, scope, $element, attributes, $window);
}
};
}
#7
0
使用angular-click-outside
Installation:
安装:
bower install angular-click-outside --save
npm install @iamadamjowett/angular-click-outside
yarn add @iamadamjowett/angular-click-outside
Usage:
用法:
angular.module('myApp', ['angular-click-outside'])
//in your html
<div class="menu" click-outside="closeThis">
...
</div>
//And then in your controller
$scope.closeThis = function () {
console.log('closing');
}
#1
63
Watch out, your solution (the Plunker provided in the question) doesn't close the popups of other boxes when opening a second popup (on a page with multiple selects).
注意,您的解决方案(在问题中提供的插入器)在打开第二个弹出窗口时(在具有多个选择的页面上)不会关闭其他框的弹出窗口。
By clicking on a box to open a new popup the click event will always be stopped. The event will never reach any other opened popup (to close them).
通过单击一个框来打开一个新的弹出窗口,单击事件将始终被停止。事件将永远不会到达任何其他打开的弹出窗口(关闭它们)。
I solved this by removing the event.stopPropagation();
line and matching all child elements of the popup.
我通过删除event.stopPropagation()来解决这个问题;行并匹配弹出窗口的所有子元素。
The popup will only be closed, if the events element doesn't match any child elements of the popup.
只有当事件元素与弹出的任何子元素不匹配时,弹出窗口才会被关闭。
I changed the directive code to the following:
我将指令码改为:
select.html (directive code)
选择。html(指令代码)
link: function(scope, element, attr){
scope.isPopupVisible = false;
scope.toggleSelect = function(){
scope.isPopupVisible = !scope.isPopupVisible;
}
$(document).bind('click', function(event){
var isClickedElementChildOfPopup = element
.find(event.target)
.length > 0;
if (isClickedElementChildOfPopup)
return;
scope.$apply(function(){
scope.isPopupVisible = false;
});
});
}
I forked your plunker and applied the changes:
我给你的活塞分叉并应用了这些变化:
Plunker: Hide popup div on click outside
柱塞:隐藏弹出式div,点击外部
Screenshot:
截图:
#2
43
This is an old post but in case this helps anyone here is a working example of click outside that doesn't rely on anything but angular.
这是一篇老文章,但如果这对任何人都有帮助的话,这是一个点击之外的工作例子,它不依赖于任何东西,除了角度。
module('clickOutside', []).directive('clickOutside', function ($document) {
return {
restrict: 'A',
scope: {
clickOutside: '&'
},
link: function (scope, el, attr) {
$document.on('click', function (e) {
if (el !== e.target && !el[0].contains(e.target)) {
scope.$apply(function () {
scope.$eval(scope.clickOutside);
});
}
});
}
}
});
#3
8
OK I had to call $apply() as the event is happening outside angular world (as per doc).
我必须调用$apply(),因为事件发生在角度世界之外(根据doc)。
element.bind('click', function(event) {
event.stopPropagation();
});
$document.bind('click', function(){
scope.isVisible = false;
scope.$apply();
});
#4
7
I realized it by listening for a global click event like so:
我通过收听这样的全球点击事件实现了这一点:
.directive('globalEvents', ['News', function(News) {
// Used for global events
return function(scope, element) {
// Listens for a mouse click
// Need to close drop down menus
element.bind('click', function(e) {
News.setClick(e.target);
});
}
}])
The event itself is then broadcasted via a News service
然后,活动本身通过新闻服务进行广播
angular.factory('News', ['$rootScope', function($rootScope) {
var news = {};
news.setClick = function( target ) {
this.clickTarget = target;
$rootScope.$broadcast('click');
};
}]);
You can then listen for the broadcast anywhere you need to. Here is an example directive:
然后你可以在任何需要的地方收听广播。这里有一个例子指令:
.directive('dropdown', ['News', function(News) {
// Drop down menu für the logo button
return {
restrict: 'E',
scope: {},
link: function(scope, element) {
var opened = true;
// Toggles the visibility of the drop down menu
scope.toggle = function() {
element.removeClass(opened ? 'closed' : 'opened');
element.addClass(opened ? 'opened' : 'closed');
};
// Listens for the global click event broad-casted by the News service
scope.$on('click', function() {
if (element.find(News.clickTarget.tagName)[0] !== News.clickTarget) {
scope.toggle(false);
}
});
// Init
scope.toggle();
}
}
}])
I hope it helps!
我希望它可以帮助!
#5
4
There is a cool directive called angular-click-outside
. You can use it in your project. It is super simple to use:
有一个很酷的指令叫做angular-click-outside。您可以在项目中使用它。使用起来超级简单:
https://github.com/IamAdamJowett/angular-click-outside
https://github.com/IamAdamJowett/angular-click-outside
#6
3
I was not totally satisfied with the answers provided so I made my own. Improvements:
我对所提供的答案并不完全满意,所以我自己做了。改进:
- More defensive updating of the scope. Will check to see if a apply/digest is already in progress
- 更多的防御性更新的范围。将检查是否已经有应用/摘要正在进行中?
- div will also close when the user presses the escape key
- 当用户按下escape键时,div也会关闭
- window events are unbound when the div is closed (prevents leaks)
- 当div被关闭时,窗口事件被解除绑定(防止泄漏)
-
window events are unbound when the scope is destroyed (prevents leaks)
当范围被破坏时,窗口事件被解除绑定(防止泄漏)
function link(scope, $element, attributes, $window) {
函数链接(范围,$元素,属性,$窗口)
var el = $element[0], $$window = angular.element($window); function onClick(event) { console.log('window clicked'); // might need to polyfill node.contains if (el.contains(event.target)) { console.log('click inside element'); return; } scope.isActive = !scope.isActive; if (!scope.$$phase) { scope.$apply(); } } function onKeyUp(event) { if (event.keyCode !== 27) { return; } console.log('escape pressed'); scope.isActive = false; if (!scope.$$phase) { scope.$apply(); } } function bindCloseHandler() { console.log('binding window click event'); $$window.on('click', onClick); $$window.on('keyup', onKeyUp); } function unbindCloseHandler() { console.log('unbinding window click event'); $$window.off('click', onClick); $$window.off('keyup', onKeyUp); } scope.$watch('isActive', function(newValue, oldValue) { if (newValue) { bindCloseHandler(); } else { unbindCloseHandler(); } }); // prevent leaks - destroy handlers when scope is destroyed scope.$on('$destroy', function() { unbindCloseHandler(); });
}
}
I get $window
directly into the link function. However, you do not need to do this exactly to get $window
.
我得到$window直接进入链接函数。但是,您不需要这样做来获得$window。
function directive($window) {
return {
restrict: 'AE',
link: function(scope, $element, attributes) {
link.call(null, scope, $element, attributes, $window);
}
};
}
#7
0
使用angular-click-outside
Installation:
安装:
bower install angular-click-outside --save
npm install @iamadamjowett/angular-click-outside
yarn add @iamadamjowett/angular-click-outside
Usage:
用法:
angular.module('myApp', ['angular-click-outside'])
//in your html
<div class="menu" click-outside="closeThis">
...
</div>
//And then in your controller
$scope.closeThis = function () {
console.log('closing');
}