web-dev-qa-db-fra.com

Masquer l'interface utilisateur angulaire Bootstrap lorsque vous cliquez en dehors

J'essaie de fermer manuellement un popover d'amorçage pour le faire fermer lorsque je clique n'importe où sur le document ou le body qui n'est pas le popover.

La chose la plus proche que j'ai trouvée pour accomplir ceci est de créer une directive ( a trouvé cette réponse ), mais c'est pour un déclencheur manuel si une variable est true ou false.

Quelqu'un pourrait-il m'aider à comprendre comment le fermer si je clique sur quelque chose qui ne fait pas partie de la popover?

Cela ne me dérange pas d'utiliser jQuery $(document).click(function(e){});. Je ne sais pas comment appeler un proche.

<div id="new_button" popover-template="plusButtonURL" popover-placement="right" popover-append-to-body="true" popover-animation="false">+</div>

Normalement, popover-trigger="focus" ferait l'affaire, cependant ma popover contient du contenu sur lequel il faut cliquer. J'ai dans mon popover un ng-click qui est ignoré si j'utilise le déclencheur focus, je recherche donc un moyen moins conventionnel de contourner cela.

45
bryan

EDITED:

Démo Plunker

Voici comment cela fonctionne (l'explication toujours longue et exhaustive):

  1. Créez une directive personnalisée vous permettant de cibler l'élément déclencheur.
  2. Créez une directive personnalisée qui est ajoutée au corps afin de rechercher l'élément déclencheur et de déclencher l'événement personnalisé lorsque l'utilisateur clique dessus.

Créez une directive personnalisée pour cibler l'élément déclencheur:

Vous devez déclencher le gestionnaire d'événements personnalisé à partir de l'élément qui a ouvert le popover (dans la démo, c'est le bouton). Le défi est que le popover est ajouté en tant que frère à cet élément et je pense toujours que les choses risquent davantage de se briser lorsque vous traversez le DOM et que vous vous attendez à ce qu'il ait une structure spécifique. Vous pouvez cibler l'élément déclencheur de plusieurs manières, mais mon approche consiste à ajouter un nom de classe unique à l'élément (je choisis «déclencheur») lorsque vous cliquez dessus. Dans ce scénario, un seul popover peut être ouvert à la fois. Vous pouvez donc utiliser un nom de classe en toute sécurité, mais vous pouvez le modifier à votre guise.

Directive personnalisée

app.directive('popoverElem', function(){
  return{
    link: function(scope, element, attrs) {
      element.on('click', function(){
        element.addClass('trigger');
      });
    }
  }
});

Appliqué au bouton

<button popover-template="dynamicPopover.templateUrl" popover-title="{{dynamicPopover.title}}" class="btn btn-default" popover-elem>Popover With Template</button>

Créez une directive personnalisée pour le corps du document (ou tout autre élément) afin de déclencher la fermeture du popover:

La dernière étape consiste à créer une directive personnalisée qui localisera l’élément déclencheur et déclenchera l’événement personnalisé pour fermer le popover lorsque l’élément auquel il est appliqué est cliqué. Bien entendu, vous devez exclure l'événement de clic initial de l'élément 'trigger', ainsi que de tous les éléments avec lesquels vous souhaitez interagir à l'intérieur de votre fenêtre popover. Par conséquent, j'ai ajouté un attribut appelé exclude-class afin que vous puissiez définir une classe que vous pouvez ajouter aux éléments dont les événements de clic doivent être ignorés (ce qui ne provoque pas la fermeture du popover).

Pour nettoyer les choses, lorsque le gestionnaire d'événements est déclenché, nous supprimons la classe de déclencheur ajoutée à l'élément déclencheur.

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)
          }
        }
      });
    }
  };
});

J'ai ajouté ceci à la balise body, de sorte que la page entière * serve de fond réversible pour le popover:

<body popover-close exclude-class="exclude">

Et, j'ai ajouté la classe exclude à l'entrée de la popover:

<input type="text" ng-model="dynamicPopover.title" class="form-control exclude">

Donc, il y a quelques ajustements et des pièges, mais je vais vous laisser cela:

  1. Vous devez définir une classe d'exclusion par défaut dans la fonction de liaison de la directive popover-close, au cas où l'une d'elles n'est pas définie.
  2. Vous devez savoir que la directive popover-close est liée à un élément. Par conséquent, si vous supprimez les styles que j'ai définis sur les éléments html et body pour leur donner une hauteur de 100%, vous risquez d'avoir des pas le remplir. 

Testé sous Chrome, Firefox et Safari.

23
jme11

UPDATE: Avec la version 1.0, nous avons ajouté un nouveau déclencheur appelé outsideClick qui fermera automatiquement la fenêtre contextuelle ou l'info-bulle lorsque l'utilisateur clique en dehors de la fenêtre.

Depuis la version 0.14.0, nous avons ajouté la possibilité de contrôler par programme le moment où votre info-bulle/popover est ouverte ou fermée via les attributs tooltip-is-open ou popover-is-open.

42
icfantv

Depuis Angular UI Bootstrap 1.0.0, il existe un nouveau déclencheur outsideClick pour les info-bulles et les popovers (introduit dans this pull pull . Dans Angular UI Bootstrap 2.0.0, le popover-trigger a été modifié pour utiliser des expressions angulaires ( ), la valeur doit donc être placée entre guillemets. Ce code fonctionnera avec les versions actuelles de angular-ui:

<div id="new_button" uib-popover-template="plusButtonURL" popover-trigger="'outsideClick'"
    popover-placement="right" popover-append-to-body="true" popover-animation="false">+</div>

Ce code fonctionnera avec les anciennes versions de Angular UI Bootstrap (avant la version 2.0.0):

<div id="new_button" uib-popover-template="plusButtonURL" popover-trigger="outsideClick"
    popover-placement="right" popover-append-to-body="true" popover-animation="false">+</div>
28
cdauth

Il existe une propriété appelée popover-trigger à laquelle vous pouvez affecter la propriété focus

<button 
      popover-placement="right" 
      popover="On the Right!" 
      popover-trigger="focus" 
      class="btn btn-default">
   Right
</button>

Cela fait l'affaire! :)

Éditer: Pour permettre de cliquer sur l’info-bulle et de ne pas déclencher la perte de la focalisation, considérez une approche semblable à celle-ci

Si vous voulez que cela fonctionne en mode angulaire, essayez de créer votre propre définition de déclencheur. Des suggestions sur la façon de faire cela peuvent être trouvées ici .

13
Patrick Motard

popover-trigger="'outsideClick'" Cela fonctionnera parfaitement.

popover-trigger="outsideClick" Ce ne sera pas. 

J'ai pris un jour pour comprendre pourquoi cela ne fonctionnait pas pour moi.

C'est parce qu'ils vérifient cela en utilisant ce code, "if (trigger === 'outsideClick')"

12
ajin

Ce que tu recherches, c'est 

<button
      popover-trigger="outsideClick" 
      class="btn btn-default">
   Right
</button>

De la documentation - Le déclencheur outsideClick fera basculer la fenêtre popover au clic et la masquera en cas de clic.

6

Vous pouvez utiliser:

Balisage

<div ng-app="Module">
    <div ng-controller="formController">
        <button uib-popover-template="dynamicPopover.templateUrl" popover-trigger="focus" 
          popover-placement="left" type="button" class="btn btn-default">
             Popover With Template
        </button>

        <script type="text/ng-template" id="myPopoverTemplate.html">
            <div>
                <span>prasad!!</span>
            </div>
        </script>
    </div>
</div>

Javascript

<script type="text/javascript">
    var app = angular.module("Module", ['ui.bootstrap']);
    app.controller("formController", ['$scope', function($scope) {
        $scope.dynamicPopover = {
            templateUrl: 'myPopoverTemplate.html'
        };
    }]);
</script>
4
Prasad Shigwan

J'ai eu le même problème et popover-trigger="'outsideClick'" a travaillé pour moi. Intéressant que la documentation n'a pas énoncé ce problème.

2
Jake Scott

Qu'en est-il de l'option 'outsideClick' dans la méthode '$ uibTooltipProvider' setTriggers. La documentation indique que "le déclencheur outsideClick provoque le basculement de l'info-bulle au clic et le masque en cas de clic." Documentation

1

Amélioration angulaire de la nouvelle version 1.x avec possibilité de cliquer à l'extérieur. mettez-le à niveau vers la nouvelle version. 

<button uib-popover-template="updatePassword.templateUrl" popover-title="Update Password" popover-trigger="outsideClick" popover-placement="right" popover-append-to-body="true">Click here</button>

son travail pour moi.

le focus ne fonctionnera pas si un bouton de soumission ou un événement de clic apparaît dans Popover. donc ce moyen utile de faire.

1
aviboy2006

1) Utilisez ng-bootstrap pour Popover.

2) Mettez à jour la version de ng-bootstrap vers la version 3.0.0 ou ultérieure . I.e npm install --save @ ng-bootstrap/ng-bootstrap @ 3.0.0

3) Après la mise à jour, vous pouvez utiliser la fonctionnalité [autoClose] de Ngbpopover.

<button type="button" class="btn btn-outline-secondary" popoverTitle="Pop title" [autoClose]="true" ngbPopover="Click anywhere or press Escape to close (try the toggling element too)">Click to toggle</button>

4) J'espère que ça aide!

0
Tejashree Patil

Ajoutez un comportement onclick="void(0)" à certains de vos éléments d’arrière-plan qui, une fois tapés, permettront d’évacuer les popovers.

Regardez https://github.com/angular-ui/bootstrap/issues/2123

0
npn