【问题标题】:Angular-ui tooltip with HTML带有 HTML 的 Angular-ui 工具提示
【发布时间】:2013-10-02 12:09:15
【问题描述】:

我目前正在我的应用程序中添加一些引导工具提示。

所有“正常”的工具提示都可以,但是当我想使用tooltip-html-unsafe 时,我得到的只是一个空的工具提示。

我的工具提示:

<a><span tooltip-placement="right" tooltip-html-safe="{{myHTMLText}}"> Help </span></a>

在 DOM 中,我有:

<div class="tooltip-inner" ng-bind-html-unsafe="content"></div>

div 的内容似乎是空的,因此工具提示中没有任何内容可显示。我试图直接在 DOM 中放入一些 HTML 文本,例如:

<div class="tooltip-inner" ng-bind-html-unsafe="content"><b>test</b></div> 并且有效。

你有什么想法吗?

【问题讨论】:

    标签: html twitter-bootstrap angularjs tooltip angular-ui-bootstrap


    【解决方案1】:

    html-unsafe 指令旨在指向它的内容。这个呢:

    <div data-ng-controller="SomeCtrl">
        <span data-tooltip-html-unsafe="{{yourContent}}" data-tooltip-placement="right">
            Help
        </span>
    </div>
    

    然后,在 SomeCtrl 中,创建一个变量来保存 html:

    $scope.yourContent = "<b>my html, yay</b>
    

    如果您想修改引导程序以从元素中获取内容,可以这样做。首先,您必须更改工具提示模板,以便它调用一个函数来获取 html:

    angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run(["$templateCache", function($templateCache) {
      $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html",
        "<div class=\"tooltip {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
        "  <div class=\"tooltip-arrow\"></div>\n" +
        "  <div class=\"tooltip-inner\" ng-bind-html-unsafe=\"getToolTipHtml()\"></div>\n" +
        "</div>\n" +
        "");
    }]);
    

    然后,为 tooltipHtmlUnsafePopup 做一个链接函数:

    .directive( 'tooltipHtmlUnsafePopup', function () {
      return {
        restrict: 'E',
        replace: true,
        scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
        templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html',
        link: function(scope, element, attrs) {
            scope.getTooltipHtml = function() {
                var elemId = '#' + scope.content;
                var htmlContent = $rootElement.find(elemId).html();
                return htmlContent;
            };
        }
      };
    })
    

    编辑:后来我从 ui-bootstrap 中提取了自定义代码,这很好,因为您现在不必修改 ui-bootstrap 即可使用它。这是提取的代码,位于名为“bootstrapx”的模块中。这仅适用于弹出框(因为我并没有真正使用工具提示),但我觉得这也应该很容易适应工具提示。

    angular.module("bootstrapx", ["bootstrapx.tpls","bootstrapx.popover","bootstrapx.popover.dismisser"]);
    angular.module("bootstrapx.tpls", ["template/popover/popover-html.html","template/popover/popover-html-unsafe.html","template/popover/popover-template.html"]);
    
    
    angular.module( 'bootstrapx.popover', [ 'ui.bootstrap.tooltip' ] )
        .directive('popover', [ function() {
            return {
                restrict: 'EA',
                priority: -1000,
                link: function(scope, element) {
                    element.addClass('popover-link');
                }
            };
        }])
        .directive('popoverHtml', [ function() {
            return {
                restrict: 'EA',
                priority: -1000,
                link: function(scope, element) {
                    element.addClass('popover-link');
                }
            };
        }])
        .directive('popoverHtmlUnsafe', [ function() {
            return {
                restrict: 'EA',
                priority: -1000,
                link: function(scope, element) {
                    element.addClass('popover-link');
                }
            };
        }])
        .directive('popoverTemplate', [ function() {
            return {
                restrict: 'EA',
                priority: -1000,
                link: function(scope, element) {
                    element.addClass('popover-link');
                }
            };
        }])
    
        .directive( 'popoverHtmlPopup', [ function() {
            return {
                restrict: 'EA',
                replace: true,
                scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' },
                templateUrl: 'template/popover/popover-html.html'
            };
        }])
        .directive( 'popoverHtml', [ '$compile', '$timeout', '$parse', '$window', '$tooltip', function ( $compile, $timeout, $parse, $window, $tooltip ) {
            return $tooltip( 'popoverHtml', 'popover', 'click' );
        }])
    
        .directive( 'popoverHtmlUnsafePopup', [ '$rootElement', function ( $rootElement ) {
            return {
                restrict: 'EA',
                replace: true,
                scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' },
                templateUrl: 'template/popover/popover-html-unsafe.html',
                link: function(scope, element) {
                    var htmlContent = '';
                    scope.$watch('content', function(value) {
                        if (!value) {
                            return;
                        }
                        var elemId = '#' + value;
                        htmlContent = $rootElement.find(elemId).html();
                    });
    
                    scope.getPopoverHtml = function() {
                        return htmlContent;
                    };
                }
            };
        }])
        .directive( 'popoverHtmlUnsafe', [ '$compile', '$timeout', '$parse', '$window', '$tooltip', function ( $compile, $timeout, $parse, $window, $tooltip ) {
            return $tooltip( 'popoverHtmlUnsafe', 'popover', 'click' );
        }])
    
        .directive( 'popoverTemplatePopup', [ '$http', '$templateCache', '$compile', '$parse', function ( $http, $templateCache, $compile, $parse) {
            return {
                restrict: 'EA',
                replace: true,
                scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' },
                templateUrl: 'template/popover/popover-template.html',
                link: function(scope, element, attrs) {
                    scope.getPopoverTemplate = function() {
                        var templateName = scope.content + '.html';
                        return templateName;
                    };
                }
            };
        }])
        .directive( 'popoverTemplate', [ '$compile', '$timeout', '$parse', '$window', '$tooltip', function ( $compile, $timeout, $parse, $window, $tooltip ) {
            return $tooltip( 'popoverTemplate', 'popover', 'click' );
        }]);
    
        angular.module("template/popover/popover-html.html", []).run(["$templateCache", function($templateCache) {
            $templateCache.put("template/popover/popover-html.html",
                "<div class=\"popover {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
                "  <div class=\"arrow\"></div>\n" +
                "\n" +
                "  <div class=\"popover-inner\">\n" +
                "      <h3 class=\"popover-title\" ng-bind=\"title\" ng-show=\"title\"></h3>\n" +
                "      <div class=\"popover-content\" ng-bind-html=\"content\"></div>\n" +
                "  </div>\n" +
                "</div>\n" +
                "");
            }]);
    
        angular.module("template/popover/popover-html-unsafe.html", []).run(["$templateCache", function($templateCache) {
            $templateCache.put("template/popover/popover-html-unsafe.html",
                "<div class=\"popover {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
                "  <div class=\"arrow\"></div>\n" +
                "\n" +
                "  <div class=\"popover-inner\">\n" +
                "      <h3 class=\"popover-title\" ng-bind=\"title\" ng-show=\"title\"></h3>\n" +
                "      <div class=\"popover-content\" ng-bind-html-unsafe=\"{{getPopoverHtml()}}\"></div>\n" +
                "  </div>\n" +
                "</div>\n" +
                "");
        }]);
    
        angular.module("template/popover/popover-template.html", []).run(["$templateCache", function($templateCache) {
        $templateCache.put("template/popover/popover-template.html",
                "<div class=\"popover {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
                "  <div class=\"arrow\"></div>\n" +
                "\n" +
                "  <div class=\"popover-inner\">\n" +
                "      <h3 class=\"popover-title\" ng-bind=\"title\" ng-show=\"title\"></h3>\n" +
                "      <div class=\"popover-content\" ng-include=\"getPopoverTemplate()\"></div>\n" +
                "  </div>\n" +
                "</div>\n" +
                "");
        }]);
    
    
        angular.module('bootstrapx.popover.dismisser', [])
            .directive( 'dismissPopovers', [ '$http', '$templateCache', '$compile', '$parse', function ( $http, $templateCache, $compile, $parse) {
                return {
                    restrict: 'A',
                    link: function(scope, element, attrs) {
                        element.bind('mouseup', function(e) {
                            var clickedOutside = true;
                            $('.popover-link').each(function() {
                                if ($(this).is(e.target) || $(this).has(e.target).length) {
                                    clickedOutside = false;
                                    return false;
                                }
                            });
                            if ($('.popover').has(e.target).length) {
                                clickedOutside = false;
                            }
                            if (clickedOutside) {
                                $('.popover').prev().click();
                            }
                        });   
                    }
                };
            }]);
    

    我在body标签上有dismissPopovers指令(这可能也适用于工具提示,你只需要修改它以满足你的需要):

    <body data-ng-controller="AppController" data-dismiss-popovers>
    

    【讨论】:

    • 根据 angular-ui 的 wiki,这是正确的语法。 http://angular-ui.github.io/bootstrap/#/tooltip你的我试过了,没用。
    • 哦,废话!你是对的,我忘了,我修改了引导程序来支持它。通常,它需要实际内容。
    • 感谢您的回答。我必须把链接功能放在哪里?
    • 好的,我找到了一种更快的方法来修复它here。但你的也很好;)
    • @simmi simmi 我已经编辑了答案以包含我使用的弹出框关闭器,希望对您有所帮助!
    【解决方案2】:

    我创建了自定义指令,它允许以非常简单的方式为 bootsrap 提供 html 工具提示。无需覆盖任何模板:

    angular.module('vermouthApp.htmlTooltip', [
    ])
    .directive('vaTooltip', ['$http', '$templateCache', '$compile', '$parse', '$timeout', function ($http, $templateCache, $compile, $parse, $timeout)
    {
        //va-tooltip = path to template or pure tooltip string
        //tooltip-updater = scope item to watch for changes when template has to be reloaded [optional (only if template is dynamic)]
        //All other attributes can be added for standart boostrap tooltip behavior (ex. tooltip-placement)
        return {
            restrict: 'A',
            scope: true,
            compile: function (tElem, tAttrs)
            {
                //Add bootstrap directive
                if (!tElem.attr('tooltip-html-unsafe'))
                {
                    tElem.attr('tooltip-html-unsafe', '{{tooltip}}');
                }
                return function (scope, element, attrs)
                {
                    scope.tooltip = attrs.vaTooltip;
                    var tplUrl = $parse(scope.tooltip)(scope);
                    function loadTemplate()
                    {
                        $http.get(tplUrl, { cache: $templateCache }).success(function (tplContent)
                        {
                            var container = $('<div/>');
                            container.html($compile(tplContent.trim())(scope));
                            $timeout(function ()
                            {
                                scope.tooltip = container.html();
                            });
                        });
                    }
                    //remove our direcive to avoid infinite loop
                    element.removeAttr('va-tooltip');
                    //compile element to attach tooltip binding
                    $compile(element)(scope);
    
                    if (angular.isDefined(attrs.tooltipUpdater))
                    {
                        scope.$watch(attrs.tooltipUpdater, function ()
                        {
                            loadTemplate();
                        });
                    } else
                    {
                        loadTemplate();
                    }
                };
            }
        };
    }]);
    

    你是这么称呼它的

     <a va-tooltip="'tooltipContent.html'" tooltip-updater="item" tooltip-placement="bottom">
                    <b><i>{{item.properties.length - propertyShowLimit + ' properties more...'}}</i></b>
                </a>
    

    模板可以是这样的:

    <script id="tooltipContent.html" type="text/ng-template">
        <span ng-repeat="prop in item.properties>
            <b>{{prop.name}}</b>:
            <span ng-repeat="val in prop.values">{{val.value}}&nbsp;</span>
            <br />
        </span>
    </script>
    

    【讨论】:

      【解决方案3】:

      现在有内置模板功能:https://angular-ui.github.io/bootstrap/#tooltip

      <a href="#" uib-tooltip-template="'myTooltipTemplate.html'">Custom template</a>
      
      <script type="text/ng-template" id="myTooltipTemplate.html">
        <span>Special Tooltip with <strong>markup</strong> and {{ dynamicTooltipText }}</span>
      </script>
      

      【讨论】:

        猜你喜欢
        • 2013-12-11
        • 2013-08-16
        • 2017-10-25
        • 1970-01-01
        • 2015-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-20
        相关资源
        最近更新 更多