Reputation: 3386
I have an HTML
page that part of it is generated using HTML
injection from a typescript
angularjs
controller using $sce
and ng-bind-html
.
My problem is that the bootstrap
tooltip style isn't applied and I only get the simple built in yellow tooltip.
My controller function that generates the HTML (not sure if it's relevant but note the comment next to the console.log
section):
public renderHtml = () => {
this.test = '<span style="text-decoration:underline" data-toggle="tooltip" data-placement="top" title="Tooltip on top">my team</span>';
console.log(this.test); // this line is logged 6 times with the same value on each page refresh
return this.$sce.trustAsHtml(this.test);
}
The HTML (I've added the exact same HTML snippet directly to the page and it works fine):
<!--bootstrap tooltip doesn't show-->
<div class="row margin-25" ng-bind-html="cdc.renderHtml()"></div>
<div>
<!--bootstrap tooltip works-->
<span style="text-decoration:underline" data-toggle="tooltip" data-placement="top" title="Tooltip on top">my team</span>
</div>
Here is the outcome (not working on left):
Upvotes: 0
Views: 1588
Reputation: 3186
As per documentation:
Opt-in functionality
For performance reasons, the Tooltip and Popover data-apis are opt-in, meaning you must initialize them yourself.
Example with your approach on jsfiddle:
angular.module('ExampleApp', [])
.controller('ExampleController', function($sce) {
this.renderHTML = () => {
return $sce.trustAsHtml('<span style="text-decoration:underline" data-toggle="tooltip" data-placement="bottom" title="Tooltip on top">my team</span>');
};
});
$(document).ready(function() {
$('span').tooltip();
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div ng-app="ExampleApp">
<div ng-controller="ExampleController as vm">
<div ng-bind-html="vm.renderHTML()"></div>
<span style="text-decoration:underline" data-toggle="tooltip" data-placement="right" title="Tooltip on top">my team</span>
</div>
</div>
Better solution is use directive:
angular.module('ExampleApp', [])
.controller('ExampleController', function($sce) {})
.directive("title", function($timeout) {
return {
link: function(scope, element) {
$timeout(function() {
$(element).tooltip()
}, 0);
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div ng-app="ExampleApp">
<div ng-controller="ExampleController as vm">
<div>
<span style="text-decoration:underline" data-toggle="tooltip" data-placement="bottom" title="Tooltip on top">my team</span>
</div>
<span style="text-decoration:underline" data-toggle="tooltip" data-placement="right" title="Tooltip on top">my team</span>
</div>
</div>
Upvotes: 1
Reputation: 1382
Bootstrap works with jQuery, meaning all interaction is called upon document.ready
, when you add new content, jQuery doesn't know how to use this new content.
There is a project that implements bootstrap the angular way: ng-bootstrap.
Instead of writing HTML in your code to add to the page, you should work using directives or components. I would recommend following the free course by codeschool, it explains how to use them, and why this is the angular way.
To simply get your tooltip to work, without doing it more in the angular way:
public renderHtml = () => {
this.test = '<span style="text-decoration:underline" data-toggle="tooltip" data-placement="top" title="Tooltip on top">my team</span>';
console.log(this.test); // this line is logged 6 times with the same value on each page refresh
$timeout(function() {
angular.element('[data-toggle="tooltip"]').tooltip(); // if you've added jQuery, angular.element simply uses jQuery
}, 0); // timeout 0 means it'll run in the next $digest cycle.
return this.$sce.trustAsHtml(this.test);
}
Upvotes: 1