Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
33
rated 0 times [  39] [ 6]  / answers: 1 / hits: 22378  / 9 Years ago, tue, september 29, 2015, 12:00:00

I am attempting to close my Angular-bootstrap popovers when clicking anywhere outside the popovers. According to an answer to this question this can now be accomplished (in version 0.13.4) by utilizing the new popover-is-open attribute: Hide Angular UI Bootstrap popover when clicking outside of it



Currently my HTML looks like so:



<div
ng-click=level.openTogglePopover()
popover-template=level.changeLevelTemplate
popover-trigger=none
popover-placement=right
popover-is-open=level.togglePopover>
<button class=btn btn-default btn-xs type=button>
<span class=glyphicon glyphicon-sort></span>
</button>
</div>


...and my relevant controller code:



vm.togglePopover = false;

vm.openTogglePopover = function() {
vm.togglePopover = !vm.togglePopover;
};


This works great for opening/closing the popover when clicking on the button referenced above. My question is, how would I extend this functionality to close the popover when clicking anywhere outside of the popover? How would I set up my event handling to accomplish this?


More From » angularjs

 Answers
10

First of all, if you want the popover to close on any click, not only the one outside of your popover, you can do it using existing UI-Bootstrap code:



<button class=btn btn-default btn-xs type=button
popover-template=level.changeLevelTemplate
popover-trigger=focus
popover-placement=right>
<span class=glyphicon glyphicon-sort></span>
</button>


The trick here is to drop the surrounding <div> and put the popover-trigger=focus right on the button.






If you need to actually close the popover only for clicks outside the popover content, then it will be more difficult. You need a new directive, like this one:



app.directive('clickOutside', function ($parse, $timeout) {
return {
link: function (scope, element, attrs) {
function handler(event) {
if(!$(event.target).closest(element).length) {
scope.$apply(function () {
$parse(attrs.clickOutside)(scope);
});
}
}

$timeout(function () {
// Timeout is to prevent the click handler from immediately
// firing upon opening the popover.
$(document).on(click, handler);
});
scope.$on($destroy, function () {
$(document).off(click, handler);
});
}
}
});


Then, in your popover template, use the directive on the outermost element:



<div click-outside=level.closePopover()>
... (actual popover content goes here)
</div>


Finally, in your controller, implement the closePopover function:



vm.closePopover = function () {
vm.togglePopover = false;
};


What we've done here is:




  • we're listening on any clicks on the document, and, if the click is outside of the element to which we added our close-popover directive:


    • we invoke whatever code was the value of close-popover


  • we also clean up after ourselves when the directive's scope is destroyed (i.e. when the popover is closed) so that we don't handle the clicks anymore.



It's not the cleanest solution, as you have to invoke the controller method from within the popover template, but it's the best I came up with.


[#64897] Friday, September 25, 2015, 9 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
zoiel

Total Points: 692
Total Questions: 90
Total Answers: 89

Location: Rwanda
Member since Thu, Feb 10, 2022
2 Years ago
;