Saltar al contenido

Ocultar ventana emergente de Bootstrap de interfaz de usuario angular al hacer clic fuera de ella

Solución:

ACTUALIZAR: Con la versión 1.0, hemos agregado un nuevo activador llamado outsideClick que cerrará automáticamente la ventana emergente o la información sobre herramientas cuando el usuario haga clic fuera de la ventana emergente o la información sobre herramientas.

A partir de la versión 0.14.0, hemos agregado la capacidad de controlar mediante programación cuándo su información sobre herramientas / ventana emergente está abierta o cerrada a través de la tooltip-is-open o popover-is-open atributos.

Desde Angular UI Bootstrap 1.0.0, hay un nuevo outsideClick disparador para información sobre herramientas y ventanas emergentes (introducido en esta solicitud de extracción. En Angular UI Bootstrap 2.0.0, el popover-trigger se ha modificado para usar expresiones angulares (Changelog), por lo que el valor debe ponerse entre comillas. Este código funcionará con las versiones actuales 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>

Este código funcionará con versiones anteriores de Angular UI Bootstrap (antes de la 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>

EDITADO:

Demostración de Plunker

Así es como funciona (la explicación aún larga y exhaustiva):

  1. Cree una directiva personalizada que le permita apuntar al elemento desencadenante.
  2. Cree una directiva personalizada que se agrega al cuerpo y encontrará el elemento desencadenante y activará el evento personalizado cuando se haga clic en él.

Cree una directiva personalizada para apuntar al elemento desencadenante:

Debe activar el controlador de eventos personalizado desde el elemento que abrió el popover (en la demostración, este es el botón). El desafío es que el popover se agrega como un hermano a este elemento y siempre creo que las cosas tienen un mayor potencial de romperse cuando atraviesas el DOM y esperas que tenga una estructura específica. Hay varias formas en que puede apuntar al elemento disparador, pero mi enfoque es agregar un nombre de clase único al elemento (elijo ‘disparador’) cuando hace clic en él. Solo se puede abrir una ventana emergente a la vez en este escenario, por lo que es seguro usar un nombre de clase, pero puede modificarlo para adaptarlo a sus preferencias.

Directiva personalizada

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

Aplicado al botón

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

Cree una directiva personalizada para el cuerpo del documento (o cualquier otro elemento) para activar el cierre del popover:

La última pieza es crear una directiva personalizada que ubicará el elemento desencadenante y activará el evento personalizado para cerrar el popover cuando se haga clic en el elemento al que se aplica. Por supuesto, debe excluir el evento de clic inicial del elemento ‘disparador’ y cualquier elemento con el que desee interactuar en el interior de su ventana emergente. Por lo tanto, agregué un atributo llamado exclude-class para que pueda definir una clase que pueda agregar a los elementos cuyos eventos de clic deben ignorarse (sin que se cierre el popover).

Para limpiar las cosas, cuando se activa el controlador de eventos, eliminamos la clase de activación que se agregó al elemento de activación.

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

Agregué esto a la etiqueta del cuerpo para que toda la página * actúe como un telón de fondo descartable para el popover:

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

Y agregué la clase de exclusión a la entrada en el popover:

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

Entonces, hay algunos ajustes y trampas, pero te lo dejo a ti:

  1. Debe establecer una clase de exclusión predeterminada en la función de enlace de la directiva popover-close, en caso de que no haya una definida.
  2. Debe tener en cuenta que la directiva popover-close está vinculada al elemento, por lo que si elimina los estilos que configuré en los elementos html y body para darles una altura del 100%, podría tener ‘áreas muertas’ dentro de su ventana gráfica si su contenido no lo hace no lo llene.

Probado en Chrome, Firefox y Safari.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *