Dynamic Content with Angular Bootstrap Tooltip

Currently, I am developing a cart application in Angular and utilizing Angular Bootstrap.

The main requirement is to display a tooltip when hovering over the cart icon, with the content of the tooltip changing based on whether the item is already in the cart or not.

Here is the snippet of HTML code:

<h3><i class="fa fa-shopping-basket" ng-click="add2Cart(item.Name)" tooltip-placement="right" uib-tooltip-html="itemtooltiptext(item.Name)" aria-hidden="true></i></h3>

Essentially, I need the tooltip text to be determined by a function that checks if the item is in the cart. According to the documentation, this can be achieved using trusted HTML.

The documentation states,

uib-tooltip-html - Accepts an expression that evaluates to an HTML string. Note that this HTML is not compiled. If compilation is necessary, consider using the uib-tooltip-template attribute option instead. It is the responsibility of the user to ensure the content is safe for DOM insertion!

My itemtooltiptext() function looks like this:

$scope.itemtooltiptext = function(name) {
  if (localStorage.getItem("cart") === null) {
    return $sce.trustAsHtml("Add " + name + " to Cart!");
  } else {
    var cart = JSON.parse(localStorage.getItem("cart"));
    for (var i = 0; i < cart.length; i++) {
      if (cart[i] == name) {
        console.log("already in cart");
        return $sce.trustAsHtml(name + "already in Cart!");
      }
    }
    return $sce.trustAsHtml("Add " + name + " to Cart!");
  }
}   

This implementation leads to an

Infinite $digest Loop Error

Referencing this discussion here:

However, my query is how to handle dynamic text scenarios using functions while avoiding this error. Should I switch to a template? I am uncertain how templates would address this issue effectively since I still require variable text from the template... Can anyone provide a solution?

Thank you.

Answer №1

It seems that using uib-tooltip-html incorrectly can lead to an infinite digest loop. Luckily, there is a helpful demo plunk that demonstrates the correct way to use it.

To utilize uib-tooltip-html, you must first obtain or calculate your HTML content, bind it to a scope variable, and then bind that variable into uib-tooltip-html.

Here's an example in JavaScript:

$scope.itemtooltiptext = function() {
    $scope.htmlTooltip = $sce.trustAsHtml('I\'ve been made <b>bold</b>!');
};
$scope.itemtooltiptext();

And here's how you would implement it in HTML:

<button uib-tooltip-html="htmlTooltip" class="btn btn-default">Tooltip</button>

If you still prefer to bind a function to your tooltip, you can do so like this:

<button uib-tooltip="{{itemtooltiptext()}}" class="btn btn-default">Tooltip</button>

Keep in mind that this approach will result in the function being invoked every digest cycle.

Answer №2

I stumbled upon a never-ending digest cycle problem when I required a dynamic tooltip... it made angular recalculate it every time as if it was a new value (even though it wasn't). To solve this, I came up with a function to store the computed value like so:

$ctrl.myObj = {
    Title: 'my title',
    A: 'first part of dynamic toolip',
    B: 'second part of dynamic tooltip',
    C: 'some other value',
    getTooltip: function () {
        // cache the tooltip
        var obj = this;
        var tooltip = '<strong>A: </strong>' + obj.A + '<br><strong>B: </strong>' + obj.B;
        var $tooltip = {
            raw: tooltip,
            trusted: $sce.trustAsHtml(tooltip)
        };
        if (!obj.$tooltip) obj.$tooltip = $tooltip;
        else if (obj.$tooltip.raw !== tooltip) obj.$tooltip = $tooltip;
        return obj.$tooltip;
    }
};

Then in the html, I accessed it in this manner:

<input type="text" ng-model="$ctrl.myObj.C"
    uib-tooltip-html="$ctrl.myObj.getTooltip().trusted">

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The ng-repeat directive is failing to properly iterate over a key-value pair when the key contains a special character such as

When using ng-repeat with key value pairs that contain special characters such as ($), it may not work properly. For example: <div ng-repeat="(key, value) in values">{{key}}</div> In this case, if the values object is defined as below: $sco ...

Looking for a list of events in Express.js?

I've been searching through the official documentation, but I couldn't find a list of events for express. Does anyone know if there's something like 'route-matched' so that I can use app.on('route-matched', () => {})? ...

What is the best way to implement a switch case with multiple payload types as parameters?

I am faced with the following scenario: public async handle( handler: WorkflowHandlerOption, payload: <how_to_type_it?>, ): Promise<StepResponseInterface> { switch (handler) { case WorkflowHandlerOption.JOB_APPLICATION_ACT ...

What could be the reason these two functions yield different outcomes?

I am currently in the process of optimizing a function to enhance performance. Previously, the old function took approximately 32 seconds, while the new one now only takes around 350 milliseconds for the same call. However, there seems to be an issue as th ...

Delaying event listeners in Angular.js by using setTimeout within a factory or service

In order to delay the first iteration of the broadcast until the controller's $watchCollection is ready, I attempted using setTimeout() but it did not work as expected. Even trying with $timeout yielded the same result. What could be causing this issu ...

Is it feasible to commit an object on Vue X through Actions?

I have a question regarding Vue X and actions (with commit). Can an object be passed as input in Commit? Similar to: ... action{ ResetLoginStats({commit}){ commit({ 'SetMutation1':false, 'SetMutation2':true, &a ...

How can I implement Before() and After() hooks within a hooks.js file for a Selenium and JavaScript project?

Within my Selenium JS / Cucumber framework, I have incorporated Before() & After() functions to handle the setup and tear down of my webdriver. To manage these functions, I decided to organize them in my customSteps.js file alongside other cucumber st ...

Variable missing in the ExpressJs view

Hey there! I'm new to Nodejs and currently experimenting with it. I've been trying to convert some of my basic Python codes to JavaScript. In one of my projects, I am sending a get request to the YouTube API and receiving 50 results in JSON forma ...

Using JQuery for sending POST requests in JavaScript

I am currently facing an issue while trying to post JSON data to a server. I have managed to do it successfully using a certain method, which is as follows: <html> <head> <script src="http://code.jquery.com/jquery-latest.min.js">< ...

What is the best method to extract data from a specific member of a list within a dictionary with AngularJS?

Within my dictionary, the structure is as follows : Dictionary<string,List<B>> a; The class B has the following format: public class B { public Int64 c; public Boolean d; } Upon performing backend processing, I have obtained a wit ...

Steps for invoking the controller method in the routeProvider resolve function

I would like to update the data and then display the view associated with this controller. Here is the code snippet: angular.module('myApp.student', ['ngRoute']) .config(['$routeProvider', function($routeProvider) { ...

Error encountered while compiling a method within a .vue component due to a syntax issue

I have been closely following a tutorial on Vue.js app development from this link. The guide instructed me to add a login() function in the block of the Login.vue file. Here is the snippet of code provided: login() { fb.auth.signInWithEmailAndPa ...

"Encountered npm error: JSON input ended unexpectedly" while trying to install express-mysql-session"

I'm currently developing a nodejs project that uses passportjs for user authentication and mysql as the database. I'm now looking to incorporate session storage by utilizing the ""express-mysql-session" package. However, when attemptin ...

There is an error in Node.js where it is unable to read the property 'path' of an undefined object

Encountering an issue with my local host while developing a React and Node application. The error message I am receiving is: UNHANDLED REJECTION TypeError: Cannot read property 'path' of undefined Despite having all npm modules installed, this ...

Detecting changes in a readonly input in Angular 4

Here is a code snippet where I have a readonly input field. I am attempting to change the value of this readonly input from a TypeScript file, however, I am encountering difficulty in detecting any changes from any function. See the example below: <inp ...

Is there a way to replicate the ctrl-F5 function using jQuery?

Is there a way to use jQuery to refresh the page and clear the cache at the same time? ...

Is there a way to modify a CSS class in Chrome that is only visible when I perform a drag action?

For the website project I am working on, I have an element that only changes its style when I drag something over it. This is achieved by adding a CSS class to it. However, editing this style has proven to be challenging because I cannot live edit it in C ...

Pass the output of one function as an argument to another function in a Node.js Express application

I'm having trouble retrieving the value declared in the first function CreateTag and using it as a variable in the second function CreateStream. Despite working with nodejs Express, I've attempted to use RETURN without success. I've tried v ...

What steps can be taken once the browser has completed all rendering processes?

I have a large form that functions on older PCs. This form is a component of a thin client system and is implemented using AngularJS to create a Single Page Application. One of the tabs on the SPA includes this form. Upon opening the form, requests are se ...

Obtain date and currency formatting preferences

How can I retrieve the user's preferences for date and currency formats using JavaScript? ...