Boa maneira de abrir / fechar dinamicamente um popover (ou tooltip) usando angular, baseado em expressão?

Eu tenho um formulário que está ligado em angular, usando-o para validação. Eu sou capaz de exibir mensagens de erro usando diretivas ng-show assim:

  This field is required.   

.. onde f é o formulário e t3 vem de uma diretiva personalizada no formulário que detecta se uma submissão foi tentada e contém funções para verificar a validade dos campos.

O que eu estou tentando realizar é mostrar a (s) mensagem (ns) de validação dentro de um popover. O popover nativo do bootstrap, ou o popover do UI Bootstrap , eu carreguei ambos. Eu também posso considerar AngularStrap se é mais fácil fazê-lo usando essa biblioteca.

O que estou enfrentando agora é a natureza dos popovers em geral – eles exibem automaticamente com base em events do usuário, como click, mouseenter, blur, etc. O que eu quero fazer é mostrar e ocultar o (s) popover (s) baseado no mesmo funções nos atributos ng-show acima. Então, quando a expressão retornar false, oculte-a e quando ela retornar true, mostre-a.

Eu sei que o bootstrap tem o .popover (‘show’) para isso, mas eu não deveria dizer algo angular sobre o dom, então eu não tenho certeza de como eu teria access ao $ (element) .popover () se fazendo isso em uma function de controlador de formulário personalizado. Estou esquecendo de algo?

Atualizar

A solução mencionada na votação duplicada ainda mostra apenas o popover no mouseenter. Eu quero forçá-lo a exibir, como se estivesse fazendo $('#popover_id').popover('show') .

Você também pode criar seus próprios gatilhos estendidos. Isso será aplicado a Tooltip e Popover.

Primeiro, estenda os acionadores da dica de ferramenta da seguinte maneira:

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

Em seguida, defina o acionador na tag HTML assim:

 

E agora você pode chamar hide e show de JavaScript, este é um show em 3 segundos.

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

Como se constata, não é muito difícil decorar a dica de ferramenta de boot ou o popover com uma diretiva personalizada. Isso está escrito em texto datilografado, mas as partes do javascript dele devem ser óbvias. Esse código único funciona para decorar uma dica de ferramenta ou um 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; } } 

Com este único código, você pode configurar a ocultação programática e a exibição de uma dica de ferramenta ou popover da seguinte maneira:

 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:

  

ou

  

Então, estamos reutilizando tudo o que vem com a dica de ferramenta ou o -toggle do ui e implementando apenas o atributo -toggle . A diretiva decorativa observa esse atributo e triggers events personalizados para mostrar ou ocultar, que são então manipulados pelo provedor da dip toolstretch do ui-bootstrap.

Atualizar:

Uma vez que esta resposta parece estar ajudando os outros, aqui está o código escrito como javascript (o typescript acima é mais ou menos compilado para 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 o ui.bootstrap 0.13.4 e mais recente:

Um novo parâmetro ( popover-is-open ) foi introduzido para controlar os popovers no ui.bootstrap oficial do ui.bootstrap . É assim que você o usa na versão mais recente:

  Click me to show the popover!  

Para o ui.bootstrap 0.13.3 e mais antigo:

Acabei de publicar uma pequena diretiva que adiciona mais controle sobre popovers no GitHub:
https://github.com/Elijen/angular-popover-toggle

Você pode usar uma variável de escopo para mostrar / ocultar o popover usando a diretiva popover-toggle="variable" como esta:

  Popover here  

Aqui está uma demonstração do Plunkr:
http://plnkr.co/edit/QeQqqEJAu1dCuDtSvomD?p=preview

Minha abordagem:

  • Acompanhe o estado do popover no modelo
  • Altere esse estado por elemento usando as diretivas apropriadas.

A ideia é deixar a manipulação do DOM para as diretivas.

Eu montei um violino que espero que dê uma explicação melhor, mas você encontrará soluções muito mais sofisticadas no UI Bootstrap que você mencionou.

jsfiddle

Marcação:

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

Da resposta de Michael Stramel, mas com uma solução angularJS completa:

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

Agora adicione esta diretiva:

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

Então na sua marcação:

  

Para outras pessoas que estão chegando, a partir da versão 0.13.4, adicionamos a capacidade de abrir e fechar programaticamente popovers por meio do atributo *-is-open -is *-is-open em dicas de ferramentas e popovers na biblioteca Angular UI Bootstrap. Assim, não há mais motivo para ter que rolar seu próprio código / solução.

Intereting Posts