Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular-ui tooltip with HTML

I am currently adding some bootstrap tooltips in my application.

All of the "normal" tooltips are ok, but when I want to use tooltip-html-unsafe, all I got is an empty tooltip.

My tooltip:

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

In the DOM, I have:

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

The div's content seems empty, so there is nothing to show in the tooltip. I tried to put directly in the DOM some HTML text like:

<div class="tooltip-inner" ng-bind-html-unsafe="content"><b>test</b></div> and it works.

Do you have an idea?

like image 796
Mencls Avatar asked Sep 26 '13 13:09

Mencls


People also ask

How do I show tooltip in HTML?

HTML: Use a container element (like <div>) and add the "tooltip" class to it. When the user mouse over this <div>, it will show the tooltip text. The tooltip text is placed inside an inline element (like <span>) with class="tooltiptext" .

How do I display tooltip in Angular 8?

Showing and hiding By default, the tooltip will be immediately shown when the user's mouse hovers over the tooltip's trigger element and immediately hides when the user's mouse leaves. On mobile, the tooltip is displayed when the user longpresses the element and hides after a delay of 1500ms.

Why tooltip is not showing in Angular?

Simply remove the culprit class uib-position-measure with javascript and then adjust the top and left styles on . tooltip . Overwrite the styling that is causing the issue with javascript.


1 Answers

The html-unsafe directive is designed to point at it's content. What about this:

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

Then, in SomeCtrl, make a variable to hold the html:

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

IF you would like to modify bootstrap to take the content from a element, it can be done like this. First, you must change the tooltip template so that it calls a function to get the 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" +
    "");
}]);

Then, make a link function for the 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;
        };
    }
  };
})

EDIT: Later I extracted the customized code from ui-bootstrap, which is good since you do not have to modify ui-bootstrap to use it now. Here is the extracted code, in a module called "bootstrapx". This is just for popovers (as I was not really using tooltips) but I feel like this should be easily adaptable for tooltips too.

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

I have the dismissPopovers directive on the body tag (this is likely applicable for tooltips too, you will just have to modify it to suit your needs):

<body data-ng-controller="AppController" data-dismiss-popovers>
like image 70
aet Avatar answered Oct 14 '22 21:10

aet