Angular UI Bootstrap Tooltip工具提示是开放的怪异行为

时间:2016-01-27 13:40:57

标签: angularjs angular-ui-bootstrap

我在我自己的一个指令中使用Angular UI Bootstrap中的tooltip指令。我想使用Bootstrap Tooltip提供的tooltip-is-open属性手动切换工具提示的可见性。 Angular UI documentation州:

tooltip-is-open <WATCHER ICON> (Default: false) - Whether to show the tooltip.

所以我假设它监视属性的值。所以我想将范围变量tooltipIsOpen绑定到属性,希望在我的指令的tooltipIsOpen函数中更改link值可以切换工具提示的可见性。

我得到的行为很奇怪。

  1. 如果我将tooltipIsOpen值绑定为表达式:tooltip-is-open="{{ tooltipIsOpen }}",则工具提示根本不会出现,但我看到DOM已正确更新(tooltip-is-open="false个开关至tooltip-is-open="true"并再次回到false)以响应鼠标事件。

  2. 如果我将tooltipIsOpen值绑定为变量:tooltip-is-open="tooltipIsOpen",则工具提示会在第一个鼠标事件后正确显示,但之后不会对任何其他事件作出反应,保持显示全部时间无法隐藏它。

  3. 我找到的工作解决方案是将tooltipIsOpen绑定为函数调用:scope.tooltipIsOpenFun = function() { return tooltipIsOpen; }tooltip-is-open="tooltipIsOpenFun()",或者作为对象属性:tooltip-is-open="tooltip.isOpen"。只有这样,工具提示才能正常工作 - 一直显示和隐藏。

  4. 我怀疑它与AngularJS观察者的工作方式有关,也与分配值时JavaScript原语和对象的处理方式有所不同。我仍然无法理解。

    问题

    有人可以一步一步地向我解释为什么解决方案 1 不起作用且 2 只能工作一次?

    指令模板(方法 2

    <div uib-tooltip="Tooltip message"
         tooltip-is-open="tooltipIsOpened">
       ...
    </div>
    

    指令链接功能

    module(...).directive(..., function() {
        return {
            link: function(scope, elem, attr) {
                /* Stop further propagation of event */
                function catchEvent(event) {
                    event.stopPropagation();
                };
    
                function showTooltip(event) {
                    scope.$apply(function() {
                        scope.tooltipIsOpened = true;
    
                        /* Hide tooltip on any click outside the select */
                        angular.element(document).on('click', hideTooltip);
                        elem.on('click', catchEvent);
                    });
                };
    
                function hideTooltip() {
                    scope.$apply(function() {
                        scope.tooltipIsOpened = false;
    
                        /* Remove previously attached handlers */
                        angular.element(document).off('click', hideTooltip);
                        elem.off('click', catchEvent);
                    });
               };
    
               scope.tooltipIsOpened = false;
    
               elem.on('mouseenter', showTooltip);
               elem.on('mouseleave', hideTooltip);
            });
    

1 个答案:

答案 0 :(得分:2)

第一种方式不正确,因为该指令需要变量名,而不是变量值。所以正确:

<div uib-tooltip="Tooltip message" tooltip-is-open="xxx">

或者更正(你传递{{}}但是你传递的不是变量的值,而是传递存储变量名的变量的值):

<div ng-init="yyy='xxx'">
    <div uib-tooltip="Tooltip message" tooltip-is-open="{{yyy}}">

第二种方式实际上以某种方式工作: http://plnkr.co/edit/OD07Oj2A0tfj60q2QKHe?p=preview 但这很奇怪 - 用户如何在不触发mouseleave事件的情况下点击外部元素?

问题是你不需要这一切,只是:

<button uib-tooltip="Tooltip message" trigger="mouseenter"
     tooltip-is-open="tooltipIsOpened">
   hello
</button>

工作正常。

第三种方式:如果你看到&#39;打开&#39;不起作用,但是&#39; smth.open&#39;通常意味着你面临的问题&#39;点问题&#39; - 您不能直接从子范围更改父范围变量,但您可以更改变量属性。这个问题有很多例子和解释。