Using Bootstrap Tooltip with AngularJS
Asked Answered
B

19

93

I am trying to use the Bootstrap tooltip in an app of mine. My app is using AngularJS Currently, I have the following:

<button type="button" class="btn btn-default" 
        data-toggle="tooltip" data-placement="left"
        title="Tooltip on left">
            Tooltip on left
</button>

I think I need to use

$("[data-toggle=tooltip]").tooltip();

However, I'm not sure. Even when I add the line above though, my code doesn't work. I'm trying to avoid using UI bootstrap as it has more than I need. However, if I had to include just the tooltip piece, I'd be open to that. Yet, I can't figure out how to do that.

Can someone show me how to get the Bootstrap Tooltip working with AngularJS?

Blasphemous answered 18/12, 2013 at 19:36 Comment(1)
Without using Angular-UI Bootstrap, you will need to do all of the bindings for your events. If you don't want to use UI Bootstrap because it has more than you need, have you considered only loading the parts that you do need: github.com/angular-ui/bootstrap/tree/master/src/popoverAyeaye
K
155

In order to get the tooltips to work in the first place, you have to initialize them in your code. Ignoring AngularJS for a second, this is how you would get the tooltips to work in jQuery:

$(document).ready(function(){
    $('[data-toggle=tooltip]').hover(function(){
        // on mouseenter
        $(this).tooltip('show');
    }, function(){
        // on mouseleave
        $(this).tooltip('hide');
    });
});

This will also work in an AngularJS app so long as it's not content rendered by Angular (eg: ng-repeat). In that case, you need to write a directive to handle this. Here's a simple directive that worked for me:

app.directive('tooltip', function(){
    return {
        restrict: 'A',
        link: function(scope, element, attrs){
            element.hover(function(){
                // on mouseenter
                element.tooltip('show');
            }, function(){
                // on mouseleave
                element.tooltip('hide');
            });
        }
    };
});

Then all you have to do is include the "tooltip" attribute on the element you want the tooltip to appear on:

<a href="#0" title="My Tooltip!" data-toggle="tooltip" data-placement="top" tooltip>My Tooltip Link</a>
Krebs answered 25/7, 2014 at 17:57 Comment(7)
Nice solution! I did replace app.directive with angular.module('tooltip', []).directive to get it to work in my application.Yelmene
Nice solution. Can we add some css on it to change tooltip?Stopper
Could add in $(element).tooltip({html: 'true', container: 'body'}) before calling tooltip show as an example on providing customized options.Biological
Is it possible to do this without jQuery? When I try to manipulate the element, it says tooltip is not a function.Sansculotte
element.tooltip() can be used instead of jQuery.Julissa
when the button directs you to a different page, the hover out is not called and stays on the page i believe - tested with console logs and this is true.Caenogenesis
Are you suggesting adding the directive to resolve the ng-repeat issue, or are you suggesting you need to add a custom directive to resolve?Predikant
H
62

The best solution I've been able to come up with is to include an "onmouseenter" attribute on your element like this:

<button type="button" class="btn btn-default" 
    data-placement="left"
    title="Tooltip on left"
    onmouseenter="$(this).tooltip('show')">
</button>
Helmsman answered 14/4, 2015 at 15:49 Comment(2)
Boostrap JS is a jQuery library. At least it was in Bootstrap 3.Helmsman
Works with Angular 2+ as well. Thanks!Wanigan
B
34

Simple Answer - using UI Bootstrap (ui.bootstrap.tooltip)

There seem to be a bunch of very complex answers to this question. Here's what worked for me.

  1. Install UI Bootstrap - $ bower install angular-bootstrap

  2. Inject UI Bootstrap as a dependency - angular.module('myModule', ['ui.bootstrap']);

  3. Use the uib-tooltip directive in your html.


<button class="btn btn-default"
        type="button"
        uib-tooltip="I'm a tooltip!">
     I'm a button!
</button>
Bridegroom answered 2/6, 2016 at 23:40 Comment(2)
No jQuery, using pure Angular and ui-bootstrap; This is what I was looking for, thanksSeadon
The only solution that worked for me. Thank you! (@Kondal - yes, it works without jQuery).Purport
P
29

If you're building an Angular app, you can use jQuery, but there is a lot of good reasons to try to avoid it in favor of more angular driven paradigms. You can continue to use the styles provided by bootstrap, but replace the jQuery plugins with native angular by using UI Bootstrap

Include the Boostrap CSS files, Angular.js, and ui.Bootstrap.js:

<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://code.angularjs.org/1.2.20/angular.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.js"></script>

Make sure you've injected ui.bootstrap when you create your module like this:

var app = angular.module('plunker', ['ui.bootstrap']);

Then you can use angular directives instead of data attributes picked up by jQuery:

<button type="button" class="btn btn-default" 
        title="Tooltip on left" data-toggle="tooltip" data-placement="left"
        tooltip="Tooltip on left" tooltip-placement="left" >
  Tooltip on left
</button>

Demo in Plunker


Avoiding UI Bootstrap

jQuery.min.js (94kb) + Bootstrap.min.js (32kb) is also giving you more than you need, and much more than ui-bootstrap.min.js (41kb).

And time spent downloading the modules is only one aspect of performance.

If you really wanted to only load the modules you needed, you can "Create a Build" and choose tooltips from the Bootstrap-UI website. Or you can explore the source code for tooltips and pick out what you need.

Here a minified custom build with just the tooltips and templates (6kb)

Pollak answered 4/8, 2014 at 14:49 Comment(1)
Worth noting that, as of writing, v 0.12.1 is for v1.2 of Angular. the 0.13 branch will be for Angular 1.3+ but the new maintainer is still working on this (and doing a great job!)Saxtuba
C
12

Have you included the Bootstrap JS and jQuery?

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.2/js/bootstrap.min.js"></script>

If you don't already load those, then Angular UI (http://angular-ui.github.io/bootstrap/) may not be much overhead. I use that with my Angular app, and it has a Tooltip directive. Try using tooltip="tiptext"

<button type="button" class="btn btn-default" 
        data-toggle="tooltip" data-placement="left"
        title="Tooltip on left"
        tooltip="This is a Bootstrap tooltip"
        tooltip-placement="left" >
            Tooltip on left
</button>
Cursorial answered 18/12, 2013 at 20:13 Comment(1)
Thanks @prototype! I was going to go for @Helmsman answer, but prefer this solution as it does not explicitly say that it needs jQuery, which make this a bit less coupled, and a bit easier to change for a fully angular solution in the future.Oralla
C
8

I wrote a simple Angular Directive that's been working well for us.

Here's a demo: http://jsbin.com/tesido/edit?html,js,output

Directive (for Bootstrap 3):

// registers native Twitter Bootstrap 3 tooltips
app.directive('bootstrapTooltip', function() {
  return function(scope, element, attrs) {
    attrs.$observe('title',function(title){
      // Destroy any existing tooltips (otherwise new ones won't get initialized)
      element.tooltip('destroy');
      // Only initialize the tooltip if there's text (prevents empty tooltips)
      if (jQuery.trim(title)) element.tooltip();
    })
    element.on('$destroy', function() {
      element.tooltip('destroy');
      delete attrs.$$observers['title'];
    });
  }
});

Note: If you're using Bootstrap 4, on lines 6 & 11 above you'll need to replace tooltip('destroy') with tooltip('dispose') (Thanks to user1191559 for this upadate)

Simply add bootstrap-tooltip as an attribute to any element with a title. Angular will monitor for changes to the title but otherwise pass the tooltip handling over to Bootstrap.

This also allows you to use any of the native Bootstrap Tooltip Options as data- attributes in the normal Bootstrap way.

Markup:

<div bootstrap-tooltip data-placement="left" title="Tooltip on left">
        Tooltip on left
</div>

Clearly this doesn't have all the elaborate bindings & advanced integration that AngularStrap and UI Bootstrap offer, but it's a good solution if you're already using Bootstrap's JS in your Angular app and you just need a basic tooltip bridge across your entire app without modifying controllers or managing mouse events.

Castillo answered 8/12, 2015 at 23:10 Comment(4)
Tried to use this and I got a Error: cannot call methods on tooltip prior to initialization; attempted to call method 'destroy' error.Finical
@CD Hmm... I'm not yet able to reproduce that error. I added this demo url to the answer: jsbin.com/tesido/edit?html,js,output If you know how your code differs, let me know and I'll see if I can help. By the way, the demo is using Angular v1.2, Bootstrap v3.3, jQuery v2.1Castillo
Thank you, this was the only one in these samples that updates the tooltip dynamically if the title changes via binding.Nuptial
BTW for BS4, you must swap the line: element.tooltip('destroy'); with element.tooltip('dispose'); in both places.Nuptial
P
4

You can use selector option for dynamic single page applications:

jQuery(function($) {
    $(document).tooltip({
        selector: '[data-toggle="tooltip"]'
    });
});

if a selector is provided, tooltip objects will be delegated to the specified targets. In practice, this is used to enable dynamic HTML content to have tooltips added.

Patch answered 21/1, 2016 at 13:19 Comment(0)
T
4

You can create a simple directive like this:

angular.module('myApp',[])
    .directive('myTooltip', function(){
        return {
            restrict: 'A',
            link: function(scope, element){
                element.tooltip();
            }
        }
    });

Then, add your custom directive where is necessary:

<button my-tooltip></button>
Tartarous answered 12/4, 2016 at 13:22 Comment(0)
D
3

You can do this with AngularStrap which

is a set of native directives that enables seamless integration of Bootstrap 3.0+ into your AngularJS 1.2+ app."

You can inject the entire library like this:

var app = angular.module('MyApp', ['mgcrea.ngStrap']); 

Or only pull in the tooltip feature like this:

var app = angular.module('MyApp', ['mgcrea.ngStrap.tooltip']); 

Demo in Stack Snippets

var app = angular.module('MyApp', ['mgcrea.ngStrap']);  
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.1.2/angular-strap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.1.2/angular-strap.tpl.min.js"></script>

<div ng-app="MyApp" class="container" >

  <button type="button" 
          class="btn btn-default" 
          data-trigger="hover" 
          data-placement="right"
          data-title="Tooltip on right"
          bs-tooltip>
    MyButton
  </button>

</div>
Distress answered 11/8, 2014 at 12:57 Comment(0)
A
2

easiest way , add $("[data-toggle=tooltip]").tooltip(); to the concerned controller.

Anne answered 29/9, 2015 at 0:22 Comment(0)
C
1

var app = angular.module('MyApp', ['mgcrea.ngStrap']);  
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.1.2/angular-strap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.1.2/angular-strap.tpl.min.js"></script>

<div ng-app="MyApp" class="container" >

  <button type="button" 
          class="btn btn-default" 
          data-trigger="hover" 
          data-placement="right"
          data-title="Tooltip on right"
          bs-tooltip>
    MyButton
  </button>

</div>
Chlordane answered 17/5, 2016 at 10:21 Comment(1)
Please add some explenation to your answer.Stoop
F
1

Please remember one thing if you want to use bootstrap tooltip in angularjs is order of your scripts if you are using jquery-ui as well, it should be:

  • jQuery
  • jQuery UI
  • Bootstap

It is tried and tested

Fennie answered 29/9, 2016 at 11:49 Comment(0)
O
1

Only read this if you are assigning tooltips dynamically

i.e. <div tooltip={{ obj.somePropertyThatMayChange }} ...></div>

I had an issue with dynamic tooltips that were not always updating with the view. For example, I was doing something like this:

This didn't work consistently

<div ng-repeat="person in people">
    <span data-toggle="tooltip" data-placement="top" title="{{ person.tooltip }}">
      {{ person.name }}
    </span> 
</div> 

And activating it as so:

$timeout(function() {
  $(document).tooltip({ selector: '[data-toggle="tooltip"]'});
}, 1500)

However, as my people array would change my tooltips wouldn't always update. I tried every fix in this thread and others with no luck. The glitch seemed to only be happening around 5% of the time, and was nearly impossible to repeat.

Unfortunately, these tooltips are mission critical for my project, and showing an incorrect tooltip could be very bad.

What seemed to be the issue

Bootstrap was copying the value of the title property to a new attribute, data-original-title and removing the title property (sometimes) when I would activate the toooltips. However, when my title={{ person.tooltip }} would change the new value would not always be updated into the property data-original-title. I tried deactivating the tooltips and reactivating them, destroying them, binding to this property directly... everything. However each of these either didn't work or created new issues; such as the title and data-original-title attributes both being removed and un-bound from my object.

What did work

Perhaps the most ugly code I've ever pushed, but it solved this small but substantial problem for me. I run this code each time the tooltip is update with new data:

$timeout(function() {
    $('[data-toggle="tooltip"]').each(function(index) {
      // sometimes the title is blank for no apparent reason. don't override in these cases.
      if ($(this).attr("title").length > 0) {
        $( this ).attr("data-original-title", $(this).attr("title"));
      }
    });
    $timeout(function() {
      // finally, activate the tooltips
      $(document).tooltip({ selector: '[data-toggle="tooltip"]'});
    }, 500);
}, 1500);

What's happening here in essence is:

  • Wait some time (1500 ms) for the digest cycle to complete, and the titles to be updated.
  • If there's a title property that is not empty (i.e. it has changed), copy it to the data-original-title property so it will be picked up by Bootstrap's toolips.
  • Reactivate the tooltips

Hope this long answer helps someone who may have been struggling as I was.

Odericus answered 29/5, 2017 at 12:21 Comment(0)
S
1

Try the Tooltip (ui.bootstrap.tooltip). See Angular directives for Bootstrap

<button type="button" class="btn btn-default" tooltip-placement="bottom" uib-tooltip="tooltip message">Test</button>

It is recommended to avoid JavaScript code on the top of AngularJS

Semiology answered 15/11, 2017 at 21:1 Comment(0)
M
1

for getting tooltips to refresh when the model changes, i simply use data-original-title instead of title.

e.g.

<i class="fa fa-gift" data-toggle="tooltip" data-html="true" data-original-title={{getGiftMessage(gift)}} ></i>

note that i'm initializing use of tooltips like this:

<script type="text/javascript">
    $(function () {
        $("body").tooltip({ selector: '[data-toggle=tooltip]' });
    })
</script>

versions:

  • AngularJS 1.4.10
  • bootstrap 3.1.1
  • jquery: 1.11.0
Medan answered 12/3, 2019 at 20:48 Comment(0)
C
0

AngularStrap doesn't work in IE8 with angularjs version 1.2.9 so not use this if your application needs to support IE8

Conant answered 17/7, 2015 at 14:28 Comment(0)
A
0

impproving @aStewartDesign answer:

.directive('tooltip', function(){
  return {
    restrict: 'A',
    link: function(scope, element, attrs){
      element.hover(function(){
        element.tooltip('show');
      }, function(){
        element.tooltip('hide');
      });
    }
  };
});

There's no need for jquery, its a late anwser but I figured since is the top voted one, I should point out this.

Appendicitis answered 28/11, 2016 at 16:21 Comment(0)
D
0

install the dependencies:

npm install jquery --save
npm install tether --save
npm install bootstrap@version --save;

next, add scripts in your angular-cli.json

"scripts": [
        "../node_modules/jquery/dist/jquery.min.js",
        "../node_modules/tether/dist/js/tether.js",
        "../node_modules/bootstrap/dist/js/bootstrap.min.js",
        "script.js"
    ]

then, create a script.js

$("[data-toggle=tooltip]").tooltip();

now restart your server.

Decade answered 25/10, 2017 at 18:54 Comment(1)
wrong angular version, original question is about AngularJS not AngularWards
A
0

Because of the tooltip function, you have to tell angularJS that you are using jQuery.

This is your directive:

myApp.directive('tooltip', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('mouseenter', function () {
                jQuery.noConflict();
                (function ($) {
                    $(element[0]).tooltip('show');
                })(jQuery);
            });
        }
    };
});

and this is how to use the directive :


<a href="#" title="ToolTip!" data-toggle="tooltip" tooltip></a>
Ansell answered 31/12, 2019 at 9:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.