Angular-UI Bootstrap toggle buttons in AngularJS - angularjs

I originally had the default Bootstrap 3.3 toggle buttons in my app. These are the grouping of buttons that mimic the behavior of checkboxes or radio buttons.
I was trying to replace them with the ones here
I paste the code into my html, and at first it looks fine:
<div class="btn-group">
<label class="btn btn-default" ng-model="checkModel.left" btn-checkbox>Left</label>
<label class="btn btn-default" ng-model="checkModel.middle" btn-checkbox>Middle</label>
<label class="btn btn-default" ng-model="checkModel.right" btn-checkbox>Right</label>
</div>
Now I want to hook up the controller. So, I create a file "elements-buttons.controller.js" with the contents of the JS from the angular-ui site:
(function() {
'use strict';
angular.module('pb.ds.elements').controller('ButtonsController',
function($log) {
var _this = this;
_this.singleModel = 1;
_this.radioModel = 'Middle';
_this.checkModel = {
left: false,
middle: true,
right: false
};
});
})();
I put the controller into my router:
.state('elements.buttons', {
url: '/elements/buttons',
templateUrl: 'modules/elements/templates/elements-buttons.html',
controller: 'ButtonsController as buttons'
})
Now, as soon as I link the controller to my index.html, the button group loses all styling:
Which makes no sense to me at all. Inspecting the code in Chrome shows it's if fact lost all its classes for some reason:
<div class="btn-group">
<label class="" ng-model="buttons.checkModel.left" btn-checkbox="">Left</label>
<label class="" ng-model="buttons.checkModel.middle" btn-checkbox="">Middle</label>
<label class="" ng-model="buttons.checkModel.right" btn-checkbox="">Right</label>
</div>
Now, since I have used "controller as" syntax, I did make sure to try adding that to the model ng-model="buttons.checkModel.right" but with or without this same thing. No controller, looks fine. Controller, boom.
EDIT/UPDATE: There are no errors in the console of any kind.

I have created a jsfiddle in order to debug your problem.
Check it here.
And Im finding no problems on it.
Key points you should check:
Be sure you are adding all neccessaries files, such as ui-bootstrap.js
ui-bootstrap.css
jquery, since this are just directives for angular, it will also need jQuery (as the original bootstrap does)
include the dependency on ui-bootstrap on you app definition, pay attention to this line -> angular.module('app', ['ui.bootstrap', 'app.controllers']);
ng-app & ng-controller on the markup. Be sure you are not forgetting this
On the fiddle, Im not using ui-router, but you should check that the controller is indeed loading (you can add a console.log there and check that the controller is loaded).
I thing with this guidelines and the jsfiddle, you should be good to go

Related

Adding dependencies to an AngularJS controller

I have inherited some AngularJS code. It has this
function MainCtrl($scope)
{
// code goes here
};
angular
.module('inspinia')
.controller('MainCtrl', MainCtrl)
Now I want to add a custom controller which combines a datepicker and timepicker into one control. The GitHub project is here and there is a demo Plunk here.
The demo Punk declares its controller as
var app = angular.module('app', ['ui.bootstrap', 'ui.bootstrap.datetimepicker']);
app.controller('MyController', ['$scope', function($scope) {
How do I add that into my existing controller? What is the combined declaration? Preferably one that I can use it with ng-stricti-di on my ng-app.
[Update] here's my best guess, which I can't test until I get home in 10 hours or so. How does it look?
var myApp=angular.module('myApp', ['$scope','ui.bootstrap','ui.bootstrap.datetimepicker']);
myApp.controller('MainCtrl', function($scope)
{
// code goes here, and can use ui.bootstrap and ui.bootstrap.datetimepicker
// which were injected into the app's module
}]);
[Update 2[ When I change it to
angular
.module('inspinia' ['ui.bootstrap', 'ui.bootstrap.datetimepicker'])
.controller('MainCtrl', MainCtrl)
I get
Error: [$injector:nomod] http://errors.angularjs.org/1.5.0/$injector/nomod?p0=undefinedError: [$injector:nomod] http://errors.angularjs.org/1.5.0/$injector/nomod?p0=undefined
Despue index.html having
<script src="js/bootstrap/bootstrap.min.js"></script>
How do I get this project to use ui boostrap and its datepicker?
Please review these steps:
You don't need to inject your $scope in your app declaration just
inject external modules you want to use, for this case:
'ui.bootstrap' and 'ui.bootstrap.datetimepicker'.
angular.module('myApp', ['ui.bootstrap','ui.bootstrap.datetimepicker'])
What is the combined declaration?
Because 'ui.bootstrap.datetimepicker' depends only on 'ui.bootstrap.dateparser' and 'ui.bootstrap.position' but you need also the bootstrap templates and functionality that are included into the ui.bootstrap-tpls.js.
Make sure to include the above files required in you index.html
<link rel="stylesheet" ref="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.1.0/ui-bootstrap-tpls.js"></script>
<!-- make sure you download this file from the github project -->
<script src="datetime-picker.js"></script>
How do I add that into my existing controller?
When you declare your controller this inherit all module dependencies you had declared (injected) for the app, so you don't need to do this again. In your controller you should create an object literal to store the date-time selected for the user and a variable to control when the date-picker is open, like this:
angular.module('myApp').controller('MainCtrl', ['$scope', function($scope) {
$scope.myDatetime = {
dateSelected: new Date(),
isOpen: false
}
}]);
Call the date-time picker directive in your html:
<html ng-app-="myApp">
<head> .... </head>
<body ng-controller="MainCtrl">
<div class="input-group">
<input type="text" class="form-control" datetime-picker="MM/dd/yyyy HH:mm" ng-model="myDatetime.dateSelected" is-open="myDatetime.isOpen" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="myDatetime.isOpen = !myDatetime.isOpen"><i class="fa fa-calendar"></i></button>
</span>
</div>
</body>
</html>
I hope this help you.
Based on your comment under the question, your confusion is with the way the two pieces of code handle their dependency injection. So before I go further, if you haven't read the documentation on dependency injection, then stop right here and go read it. It will have all of your answers and more and it's something you need to know if handling Angular for longer than five minutes.
To answer the specific case you have, the top code you listed uses implicit injection for the controller which works but is not safe for minification nor is it recommended. The code sample you found uses array dependency inject for the controller which is better and safe for minification. The app declaration in the second sample is just standard module dependency injection and shouldn't look any different than what you already have in your application.
So to use the code you found all you have to do is add the correct module dependencies to your app something like:
angular.module('inspinia', ['ui.bootstrap', 'ui.bootstrap.datetimepicker']);
angular.module('inspinia').controller('MainCtrl',MainCtrl);
function MainCtrl($scope) { }
Your controller appears to already have the correct dependencies so it doesn't need to be changed (which is say it doesn't need anything outside of $scope). I used the code from your first example to show how your current code would be updated but ideally you would use the second version of dependency inject for your controller.
The update you have with the error is because the ui.bootstrap module is not part of bootstrap but part of the angular-bootstrap project. You need to include those js in your page.
It would be remiss of me if I didn't go ahead and mention there is a third way to do dependency injection using the $inject service. It is preferred in a number of popular style guides because it is easy to use a task runner to automate. This is arguably the best option to use for this reason.
Here is minimal app, that you will need to use this datepicker
Html:
<body ng-app="inspinia">
<div ng-controller="MainCtrl as ctrl">
<h1>Datepicker Demo</h1>
<div class="row">
<div class="col-md-6">
<p class="input-group">
<input type="text" class="form-control" uib-datepicker-popup ng-model="ctrl.dt" is-open="ctrl.opened" close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="ctrl.open()"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
</div>
</div>
</body>
JavaScript:
(function() {
'use strict';
angular.module('inspinia', ['ui.bootstrap']);
angular.module('inspinia').controller('MainCtrl', MainCtrl);
function MainCtrl() {
this.open = function() {
this.opened = true;
};
this.opened = false;
}
})();
Here I created a plunker for you, so you can try:
http://plnkr.co/edit/jEwT39sKcKtr8jbQa0uc?p=preview

AngularJS Modal not showing up when templateUrl changes

So far, what I have is straight off the Angular UI example:
Controller:
var ModalDemoCtrl = function ($scope, $modal) {
$scope.open = function () {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl
});
};
};
var ModalInstanceCtrl = function ($scope, $modalInstance) {
$scope.close = function () {
$modalInstance.dismiss('cancel');
};
};
And this section, which is just in sitting in the .html for the whole page this modal is on.
Html:
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
<button class="btn btn-warning" ng-click="close()">X</button>
</div>
<div class="modal-body">
Stuff
</div>
</script>
This works just fine. But I'm trying to refactor some things out and organize my code, so I would like to move the modal html to its own file. When I do so, and try to use it as by changing the templateUrl to the path: \tmpl\myModalContent.html, it doesn't show up. The backdrop still appears and inspecting the page shows that it loaded correctly, but just won't show up.
I've tried changing the css for the modal per these suggestions with no difference.
My question is, why does this work fine if the script tag is in the main html, but not at all if it is in it's own file?
Here is a plnkr that shows what I mean. If you copy what is in the template.html and place it right above the button in the index.html file, it works...
Remove template declaration for template.html and just put raw HTML in there like this:
<!--script type="text/ng-template" id="template.html"-->
<div class="modal-body">
Hello
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="cancel()">OK</button>
</div>
<!--/script-->
Your plnkr worked fine with second click to the button. It'd show the modal as expected. The reason it showed up with second click is because Angular would load up the 'uncompiled' template the first time, then it compiled the template to raw HTML which is ready for your subsequent clicks.
EDIT: Also, when you put the template code right in index.html, Angular compiles the template during its initial pass through the DOM; that's why the modal seemed to work.
Well I am clearly a dummy. All I had to do was include my new file in the main view.
<div ng-include="'path-to-file.html'"></div>
Then calling it from the controller was easy, all I needed was the id (modalContent.html) as the templateUrl.
Just keep swimming, and you'll eventually get there :)

Bootstrap 3 Tooltips with Angular

I'm attempting to use Boostrap 3 tooltips with Angular JS so that the tooltip displays the value of an object in the Angular scope. This works fine when the page loads, but when the value of the object in the scope is updated the tooltip still displays the original value.
HTML:
<div ng-app>
<div ng-controller="TodoCtrl">
<span data-toggle="tooltip" data-placement="bottom" title="{{name}}">Hello {{name}}</span>
<button type="button" ng-click="changeName()">Change</button>
</div>
Javascript:
function TodoCtrl($scope) {
$scope.name = 'Ian';
$scope.changeName = function () {
$scope.name = 'Alan';
}
}
$(document).ready(function () {
$('span').tooltip();
});
There's an example demonstrating my code so far and the issue in this Fiddle
Instead of:
<span data-toggle="tooltip" data-placement="bottom" title="{{name}}">Hello {{name}}</span>
Use:
<span data-toggle="tooltip" data-placement="bottom" data-original-title="{{name}}">Hello {{name}}</span>
Bootstrap Tooltip first checks data-original-title, so as long as you keep this value updated, you'll be fine. Check out this working Fiddle
My guess is that it is missing an apply for changed values, so angular knows nothing about that and does not update. I recommend angular ui bootstrap instead of raw bootstrap components for this reason.
http://angular-ui.github.io/bootstrap/
This way there is no need for jquery which is a bonus in my book.
EDIT:
try this in change handler for a quick and dirty workaround:
$('span').tooltip('hide')
.attr('data-original-title', $scope.name)
.tooltip('fixTitle');
But as i said, check out angular version as this hack has several issues....
For Latest Angular Versions Use: [attr.data-original-title]="dynamicTooltipMsg"
<button
data-toggle="tooltip"
[data-title]="dynamicTooltipMsg"
[attr.data-original-title]="dynamicTooltipMsg">
Testing
</button>

AngularStrap close modal with controller

I'm using AngularStrap with bootstrap.
I have a modal dialog that uses it's own controller. How can I close the modal using this local controller?
I instantiate the controller on a button like this:
<button type="button"
class="btn btn-success btn-lg"
bs-modal="modal"
data-template="user-login-modal.html"
data-container="body"
ng-controller="userLoginController"
>Click here to log in</button>
and the userLoginController has this:
$scope.authenticate = function(){
this.hide(); // this doesn't work
}
This is obviously just a demo, I want it to close on successful login, but this is where the code I'd use to close it would go.
I've tried instantiating the modal programmatically (use the $modal service to create the modal) but I haven't been able to figure out how to inject the controller through that method.
If I were to do something like emit an event from the modal using the bs-modal directive, how can I reference the modal to close it?
here's my plnkr:
http://plnkr.co/edit/m5gT1HiOl1X9poicWIEi?p=preview
When in the on-click function do
$scope.myClickEvent = function () {
this.$hide();
}
Figured out a good method:
I moved the ng-controller to the TEMPLATE and instantiate the modal using the provided modal service. I then use a rootscope broad cast to let everyone know that someone successfully logged in.
new controller code:
var loginModal = $modal({template:'/template.html', show:false});
$scope.showLogin = function(){
loginModal.$promise.then(loginModal.show);
}
$scope.$on("login", function(){
loginModal.$promise.then(loginModal.hide);
});
the button just looks like this now:
<button type="button"
class="btn btn-success btn-lg"
ng-click="showLogin()"
>Click here to log in</button>
and my template has the old ng-controller in the first tag.
I am probably too late, but just wish to share my answer. If all you need is hiding the modal after form success, then bind that $hide function to one of controller varriable.
<div class="modal" data-ng-controller="Controller" data-ng-init="bindHideModalFunction($hide)">
In the controller:
// Bind the hiding modal function to controller and call it when form is success
$scope.hideModal;
$scope.bindHideModalFunction =function(hideModalFunction){
$scope.hideModal = hideModalFunction;
}
I found all of the above answers way too complicated for your use case (and mine when I ran into this problem).
All you need to do, is chain the ng-click to use the built in $hide() function that angular strap bundles.
So your ng-click would look like: ng-click="authenticate();$hide()"
Using Angular and bootstrap if you want to submit data to controller then have the modal close just simply add onclick="$('.modal').modal('hide')" line to the submit button. This way it will hit the controller and close the modal. If you use data-dismiss="modal" in the button submit never hits the controller. At least for me it didn't. And this is not to say my method is a best practice but a quick one liner to get data to at least submit and close out the modal.
<div class="modal fade" id="myModal" ng-controller="SubmitCtrl">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
<form ng-submit="submit()">
<input type="text" ng-model="name" />
<button type="submit" onclick="$('.modal').modal('hide')">Submit</button>
</form>
</div>
</div>
</div>
</div>
Perhaps open it with the service on click and have it close itself on the $destroy event?
$scope.openModal = function()
{
$scope.modal = $modal({
template: "user-login-modal.html",
container="body"
});
}
$scope.$on("$destroy", function()
{
if ($scope.modal)
{
$scope.modal.hide();
}
});

Using Bootstrap Tooltip with AngularJS

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?
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>
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>
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.
Install UI Bootstrap - $ bower install angular-bootstrap
Inject UI Bootstrap as a dependency - angular.module('myModule', ['ui.bootstrap']);
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>
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)
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>
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.
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.
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>
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>
easiest way , add $("[data-toggle=tooltip]").tooltip(); to the concerned controller.
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>
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
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.
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
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
AngularStrap doesn't work in IE8 with angularjs version 1.2.9 so not use this if your application needs to support IE8
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.
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.
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>

Resources