I want to show angular UI bootsrap tooltip only when the text is truncated. I tried the below code with custom directive
<div tooltip="{{value}}" tooltip-append-to-body="true" enable-truncate-tooltip>{{value}}</div>
.directive("enableTruncateTooltip", function () {
return {
restrict: 'A',
link: function (scope, elem, attr) {
elem.bind('mouseenter', function () {
var $this = angular.element(this);
if (this.offsetWidth >= this.scrollWidth) {
angular.element('.tooltip').attr('hide-tooltip', true);
}
});
}
}
})
It works fine in angular-ui-bootstrap version 0.12.1. But later versions are not supporting this.
How can i achieve this same functionality in latest version of angular-ui-bootstrap?
Thanks in advance for your help.
We can use matTooltipDisabled property to show tooltip conditionally as shown below. We can bind a variable or we can pass a function to [matTooltipDisabled] to toggle the visibilty of material tooltip. Instead of that we can pass an expression to [matTooltip] to display or hide the tooltip as shown below.
TL;DR: Plunker Demo (using $watch) Old demo (using $timeout)
(The answer was updated to reflect a suggestion to use $watch instead of $timeout, thanks for the comment Michael Mish Kisilenko!)
First of all, change your angular-ui directives to the updated ones (prefix with 'uib-'):
<div uib-tooltip="{{value}}" show-tooltip-on-text-over-flow tooltip-enable="false">{{value}}</div>
And then use the following directive, which dynamically changes the angular-ui provided feature tooltip-enable
(note that you should initialize the element with directive tooltip-enable="false"
so the tooltip will be disabled if the text is not truncated:
myApp.directive("showTooltipOnTextOverflow", ["$timeout", function($timeout) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var el = element[0];
scope.$watch(function(){
return el.scrollWidth;
}, function() {
var el = element[0];
if (el.offsetWidth < el.scrollWidth) {
//console.log('ellipsis is active for element', element);
attrs.tooltipEnable = "true";
} else {
//console.log('ellipsis is NOT active for element', element);
}
});
/*$timeout(function() {
var el = element[0];
if (el.offsetWidth < el.scrollWidth) {
//console.log('ellipsis is active for element', element);
attrs.tooltipEnable = "true";
} else {
//console.log('ellipsis is NOT active for element', element);
}
});*/
}
};
}]);
To truncate the text i'll use plain CSS:
span.truncated {
width: 400px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
Using watch as mentioned in answer posted by Lulu will bring performance down. It will add so many watchers as many cells grid has and these get evaluated in each digest cycle.
I modified his code to use mouseover approach - so the need of tooltip is evaluated in mouseover event only on particular cell:
myApp.directive("showTooltipOnTextOverflow", ["$timeout", function($timeout) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var el = element[0];
if (angular.isObject(el)) {
var evaluateTooltip = (event: JQueryEventObject, isOurEvent: boolean) => {
// evaluate whether to enable tooltip
attrs.tooltipEnable = el.offsetWidth < el.scrollWidth ? "true" : "false";
if (isOurEvent !== true && attrs.tooltipEnable === "true") {
// tooltip should be enabled, trigger mouseover again to trigger tooltip (current mouseover is already handled by tooltip with false value)
// and mark it as our event to avoid its handling here
element.trigger("mouseover", [true]);
// revert tooltip enabling back to false to cover case when mouseover happens and tooltip should not be enabled
scope.$applyAsync(() => {
attrs.tooltipEnable = "false";
});
}
};
element.on("mouseover", evaluateTooltip);
element.on("$destroy", () => {
element.off("mouseover", evaluateTooltip);
});
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With