¿Una buena forma de abrir / cerrar dinámicamente un popover (o tooltip) usando angular, basado en la expresión?

Tengo un formulario que está conectado a angular, usándolo para validación. Puedo mostrar mensajes de error usando las directivas ng-show de esta manera:

  This field is required.   

.. donde f es el formulario, y t3 proviene de una directiva personalizada en el formulario que detecta si se intentó un envío, y contiene funciones para verificar la validez de los campos.

Lo que bash lograr es mostrar los mensajes de validación dentro de un popover. O bien popover nativo de bootstrap, o el popover de UI Bootstrap , ambos he cargado. También puedo considerar AngularStrap si es más fácil hacerlo usando esa lib.

Lo que estoy luchando ahora es la naturaleza de los popovers en general: se muestran automáticamente en función de los eventos del usuario, como hacer clic, mouseenter, desenfoque, etc. Lo que quiero hacer es mostrar y ocultar los popover basados ​​en el mismo funciones en los atributos ng-show anteriores. De modo que cuando la expresión devuelve falso, ocúltela, y cuando devuelva verdadero, muéstresela.

Sé que bootstrap tiene el .popover (‘show’) para esto, pero se supone que no debo decir nada angular sobre el dom, así que no estoy seguro de cómo tendría acceso a $ (element) .popover () si haciendo esto en una función de controlador de formulario personalizado. ¿Me estoy perdiendo de algo?

Actualizar

La solución mencionada en el voto duplicado todavía muestra el popover en mouseenter. Quiero forzarlo a mostrar, como si hiciera $('#popover_id').popover('show') .

También puedes construir tus propios disparadores extendidos. Esto se aplicará tanto a Tooltip como a Popover.

Primero, extienda los desencadenadores Tooltip de la siguiente manera:

 // define additional triggers on Tooltip and Popover app.config(['$tooltipProvider', function($tooltipProvider){ $tooltipProvider.setTriggers({ 'show': 'hide' }); }]); 

A continuación, defina el activador en la etiqueta HTML de esta manera:

 

Y ahora puedes llamar a ocultar y mostrar desde JavaScript, este es un espectáculo en 3 segundos.

 $("#RegisterHelp").trigger('show'); //Close the info again $timeout(function () { $("#RegisterHelp").trigger('hide'); }, 3000); 

Resulta que no es muy difícil decorar ui-bootstrap tooltip o popover con una directiva personalizada. Esto está escrito en texto typescript, pero las partes de JavaScript deben ser obvias. Esta única pieza de código funciona para decorar ya sea una información sobre herramientas o un popover:

 'use strict'; module App.Directives.TooltipToggle { export interface DirectiveSettings { directiveName: string; directive: any[]; directiveConfig?: any[]; } export function directiveSettings(tooltipOrPopover = 'tooltip'): DirectiveSettings { var directiveName = tooltipOrPopover; // events to handle show & hide of the tooltip or popover var showEvent = 'show-' + directiveName; var hideEvent = 'hide-' + directiveName; // set up custom triggers var directiveConfig = ['$tooltipProvider', ($tooltipProvider: ng.ui.bootstrap.ITooltipProvider): void => { var trigger = {}; trigger[showEvent] = hideEvent; $tooltipProvider.setTriggers(trigger); }]; var directiveFactory = (): any[] => { return ['$timeout', ($timeout: ng.ITimeoutService): ng.IDirective => { var d: ng.IDirective = { name: directiveName, restrict: 'A', link: (scope: ng.IScope, element: JQuery, attr: ng.IAttributes) => { if (angular.isUndefined(attr[directiveName + 'Toggle'])) return; // set the trigger to the custom show trigger attr[directiveName + 'Trigger'] = showEvent; // redraw the popover when responsive UI moves its source var redrawPromise: ng.IPromise; $(window).on('resize', (): void => { if (redrawPromise) $timeout.cancel(redrawPromise); redrawPromise = $timeout((): void => { if (!scope['tt_isOpen']) return; element.triggerHandler(hideEvent); element.triggerHandler(showEvent); }, 100); }); scope.$watch(attr[directiveName + 'Toggle'], (value: boolean): void => { if (value && !scope['tt_isOpen']) { // tooltip provider will call scope.$apply, so need to get out of this digest cycle first $timeout((): void => { element.triggerHandler(showEvent); }); } else if (!value && scope['tt_isOpen']) { $timeout((): void => { element.triggerHandler(hideEvent); }); } }); } }; return d; }]; }; var directive = directiveFactory(); var directiveSettings: DirectiveSettings = { directiveName: directiveName, directive: directive, directiveConfig: directiveConfig, }; return directiveSettings; } } 

Con esta única pieza de código, puede configurar ocultar programáticamente y mostrar ya sea una información sobre herramientas o popover como esta:

 var tooltipToggle = App.Directives.TooltipToggle.directiveSettings(); var popoverToggle = App.Directives.TooltipToggle.directiveSettings('popover'); var myModule = angular.module('my-mod', ['ui.bootstrap.popover', 'ui.bootstrap.tpls']) .directive(tooltipToggle.directiveName, tooltipToggle.directive) .config(tooltipToggle.directiveConfig) .directive(popoverToggle.directiveName, popoverToggle.directive) .config(popoverToggle.directiveConfig); 

Uso:

  

o

  

Así que estamos reutilizando todo lo que viene con ui-bootstrap tooltip o popover, y solo implementamos el atributo -toggle . La directiva decorativa observa ese atributo y dispara eventos personalizados para mostrar u ocultar, que luego son manejados por el proveedor de información sobre herramientas de ui-bootstrap.

Actualizar:

Dado que esta respuesta parece estar ayudando a otros, aquí está el código escrito como javascript (el typescript anterior más o menos comstack a este javascript):

 'use strict'; function directiveSettings(tooltipOrPopover) { if (typeof tooltipOrPopover === "undefined") { tooltipOrPopover = 'tooltip'; } var directiveName = tooltipOrPopover; // events to handle show & hide of the tooltip or popover var showEvent = 'show-' + directiveName; var hideEvent = 'hide-' + directiveName; // set up custom triggers var directiveConfig = ['$tooltipProvider', function ($tooltipProvider) { var trigger = {}; trigger[showEvent] = hideEvent; $tooltipProvider.setTriggers(trigger); }]; var directiveFactory = function() { return ['$timeout', function($timeout) { var d = { name: directiveName, restrict: 'A', link: function(scope, element, attr) { if (angular.isUndefined(attr[directiveName + 'Toggle'])) return; // set the trigger to the custom show trigger attr[directiveName + 'Trigger'] = showEvent; // redraw the popover when responsive UI moves its source var redrawPromise; $(window).on('resize', function() { if (redrawPromise) $timeout.cancel(redrawPromise); redrawPromise = $timeout(function() { if (!scope['tt_isOpen']) return; element.triggerHandler(hideEvent); element.triggerHandler(showEvent); }, 100); }); scope.$watch(attr[directiveName + 'Toggle'], function(value) { if (value && !scope['tt_isOpen']) { // tooltip provider will call scope.$apply, so need to get out of this digest cycle first $timeout(function() { element.triggerHandler(showEvent); }); } else if (!value && scope['tt_isOpen']) { $timeout(function() { element.triggerHandler(hideEvent); }); } }); } }; return d; }]; }; var directive = directiveFactory(); var directiveSettings = { directiveName: directiveName, directive: directive, directiveConfig: directiveConfig, }; return directiveSettings; } 

Para ui.bootstrap 0.13.4 y más reciente:

Se introdujo un nuevo parámetro ( popover-is-open ) para controlar los ui.bootstrap repository oficial de ui.bootstrap . Así es como lo usas en la última versión:

  Click me to show the popover!  

Para ui.bootstrap y anterior:

Acabo de publicar una pequeña directiva que agrega más control sobre los popovers en GitHub:
https://github.com/Elijen/angular-popover-toggle

Puede usar una variable de ámbito para mostrar / ocultar el popover utilizando la directiva popover-toggle="variable" siguiente manera:

  Popover here  

Aquí hay una demo Plunkr:
http://plnkr.co/edit/QeQqqEJAu1dCuDtSvomD?p=preview

Mi acercamiento:

  • Seguir el estado del popover en el modelo
  • Cambie este estado por elemento usando las directivas apropiadas.

La idea es dejar la manipulación DOM a las directivas.

He creado un violín que espero les dé una mejor explicación, pero encontrarán soluciones mucho más sofisticadas en UI Bootstrap que usted mencionó.

jsfiddle

Margen:

 
Popover
{{ element.name }}

JS:

 function DemoCtrl($scope) { $scope.elements = [ {name: 'Element1 (Error)', error: true, hovered: false}, {name: 'Element2 (no error)', error: false, hovered: false}, {name: 'Element3 (Error)', error: true, hovered: false}, {name: 'Element4 (no error)', error: false, hovered: false}, {name: 'Element5 (Error)', error: true, hovered: false}, ]; $scope.popoverShow = function(element) { element.hovered = true; } $scope.popoverHide = function(element) { element.hovered = false } } 

De la respuesta de Michael Stramel, pero con una solución angularJS completa:

 // define additional triggers on Tooltip and Popover app.config(['$tooltipProvider', function($tooltipProvider){ $tooltipProvider.setTriggers({ 'show': 'hide' }); }]) 

Ahora agregue esta directiva:

 app.directive('ntTriggerIf', ['$timeout', function ($timeout) { /* Intended use: 
*/ return { restrict: 'A', link: function (scope, element, attrs) { attrs.$observe('ntTriggerIf', function (val) { try { var ob_options = JSON.parse(attrs.ntTriggerIf.split("'").join('"') || ""); } catch (e) { return } $timeout(function () { for (var st_name in ob_options) { var condition = ob_options[st_name]; if (condition) { element.trigger(st_name); } } }) }) } } }])

Luego en tu marcado:

  

Para otros que vienen aquí, a partir de la versión 0.13.4, hemos agregado la capacidad de abrir y cerrar programáticamente popovers mediante el atributo *-is-open tanto en información sobre herramientas como en elementos emergentes en la biblioteca Bootstrap de UI angular. Por lo tanto, ya no hay ninguna razón para tener que rodar su propio código / solución.