strap angularjs twitter-bootstrap popover angular-ui-bootstrap angular-strap

strap - tooltip angularjs



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

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:

<span ng-show="t3.f.needsAttention(f.fieldName)" ng-cloak> <span ng-show="f.fieldName.$error.required && !f.fieldName.$viewValue"> This field is required. </span> </span>

.. 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 intento 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'') .


Para ui.bootstrap 0.13.4 y más reciente:

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

<a uib-popover="Hello world!" popover-is-open="isOpen" ng-click="isOpen = !isOpen"> Click me to show the popover! </a>

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:

<span popover="Hello world!" popover-toggle="isOpen"> Popover here </span>

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


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: <div nt-trigger-if={ ''triggerName'':{{someCodition === SomeValue}},''anotherTriggerName'':{{someOtherCodition === someOtherValue}} } ></div> */ 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:

<span tooltip-trigger="show" tooltip="Login or register here" nt-trigger-if="{''show'':{{ (errorConidtion) }}, ''hide'':{{ !(errorConidtion) }} }"></span>


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:

<div ng-repeat="element in elements" class="element"> <!-- Only want to show a popup if the element has an error and is being hovered --> <div class="popover" ng-show="element.hovered && element.error" ng-style>Popover</div> <div class="popoverable" ng-mouseEnter="popoverShow(element)" ng-mouseLeave="popoverHide(element)"> {{ element.name }} </div> </div>

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


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.


Resulta que no es muy difícil decorar ui-bootstrap tooltip o popover con una directiva personalizada. Esto está escrito en texto mecanografiado, 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<void>; $(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:

<span tooltip="This field is required." tooltip-toggle="formName.fieldName.$error.required" tooltip-animation="false" tooltip-placement="right"></span>

o

<span popover="This field is required." popover-toggle="formName.fieldName.$error.required" popover-animation="false" popover-placement="right"></span>

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 mecanografiado anterior más o menos compila 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; }


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:

<div id="RegisterHelp" popover-trigger="show" popover-placement="left" popover="{{ ''Login or register here''}}">

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