J'essaie de fermer mon Angular-bootstrap popover
s en cliquant n'importe où en dehors des popovers. Selon une réponse à cette question, cela peut maintenant être accompli (dans la version 0.13.4) en utilisant le nouveau popover-is-open
attribut: Masquer Angular UI Bootstrap popover lorsque vous cliquez en dehors de celui-ci
Actuellement, mon HTML ressemble à ceci:
<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>
... et mon code de contrôleur pertinent:
vm.togglePopover = false;
vm.openTogglePopover = function() {
vm.togglePopover = !vm.togglePopover;
};
Cela fonctionne très bien pour ouvrir/fermer le popover en cliquant sur le bouton référencé ci-dessus. Ma question est, comment pourrais-je étendre cette fonctionnalité pour fermer le popover en cliquant n'importe où en dehors du popover? Comment configurer ma gestion d'événements pour y parvenir?
Tout d'abord, si vous souhaitez que le popover se ferme sur n'importe quel clic, pas seulement celui à l'extérieur de votre popover, vous pouvez le faire en utilisant le code UI-Bootstrap existant:
<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>
L'astuce ici est de supprimer le <div>
et mettez le popover-trigger="focus"
à droite du bouton.
Si vous devez fermer le popover uniquement pour les clics en dehors du contenu du popover, cela sera plus difficile. Vous avez besoin d'une nouvelle directive, comme celle-ci:
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);
});
}
}
});
Ensuite, dans votre modèle popover, utilisez la directive sur l'élément le plus externe:
<div click-outside="level.closePopover()">
... (actual popover content goes here)
</div>
Enfin, dans votre contrôleur, implémentez la fonction closePopover
:
vm.closePopover = function () {
vm.togglePopover = false;
};
Ce que nous avons fait ici, c'est:
close-popover
directive: close-popover
Ce n'est pas la solution la plus propre, car vous devez invoquer la méthode du contrôleur à partir du modèle popover, mais c'est la meilleure que j'ai trouvée.
Depuis angular-ui 1.0.0, il existe un nouveau déclencheur outsideClick
pour les info-bulles et les popovers (introduit dans cette demande de tirage :
<div
uib-popover-template="level.changeLevelTemplate"
popover-trigger="outsideClick"
popover-placement="right">
<button class="btn btn-default btn-xs" type="button">
<span class="glyphicon glyphicon-sort"></span>
</button>
</div>
Si j'ai bien compris, vous souhaitez que le popover se ferme lorsqu'un utilisateur clique à peu près n'importe où, sauf à l'intérieur du popover lui-même, sauf le bouton de fermeture réel. Cela pourrait être accompli avec un écouteur d'événement:
$('html').click(function() {
if(!$(event.target).is('#foo')) {
// Code to hide/remove popovers
}
});
Découvrez ceci plunkr .
Ou, dans votre scénario spécifique:
$('html').click(function() {
if(!$(event.target).is('.my-popover-class')) {
vm.togglePopover = false;
}
})
fermez le popover lorsque vous cliquez n'importe où en dehors du popover
Il y a quelque temps, j'ai trouvé cette réponse utile: Comment rejeter un Twitter Bootstrap popover en cliquant à l'extérieur?
Le code que j'ai utilisé dans une de mes démos (mélanger angular
et jQuery
event manipulation qui n'est probablement pas recommandée) est spécifique à mes besoins mais peut donner une idée:
app.directive("eventlistener", function($rootScope) {
$(window).resize($rootScope.closeAllPopovers); // because Bootstrap popovers don't look good when misplaced
return {
link: function(scope, element, attrs) {
$('body').on('mouseup touchend', $rootScope.closeAllPopovers);
}
};
});
$rootScope.closeAllPopovers = function (e) {
$('[data-toggle="popover"]').each(function () {
if (e) {
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('hide');
}
} else {
// No event passed - closing all popovers programmatically
$(this).popover('hide');
}
});
};
Je suggère également de regarder la différence entre:
Vous allez devoir gérer l'événement vous-même comme lorsque vous utilisez le nouveau *-is-open
attributs, il n'y a pas de gestion d'événement.
Si vous n'avez pas besoin du contrôle programmatique pour ouvrir/fermer le popover, vous pouvez utiliser le déclencheur focus
intégré pour vous donner ce que vous voulez.