Creating Dynamic Popover Content with Bootstrap 5 Using an Asynchronous Function

Trying to create a bootstrap 5 popover with dynamic content by using an asynchronous function has been quite a challenge. Here is how I am setting up my popover:

document.querySelectorAll('[data-bs-toggle="popover"]').forEach(function (popover) {

    new bootstrap.Popover(popover, {
        content: function () {
            (async () => {

                var x = await PopulatePopoverContent();
                return x;

            })()
        }
    });   
});

The next step involves fetching data from the database within the function SetPopoverContent():

async function SetPopoverContent(popOver) {
    
    let contentText = '';
    let data = await dotNetReference.invokeMethodAsync('GetChatToInfo', messageId);
    if (data != null && data != undefined) {
        var outerDiv = '<div></div>';
        ...
        
        contentText = outerDiv.innerHTML;
    }
    else {

        contentText = '<p>Loading</p>';
    }
    
    return contentText;
}

Although I can observe the HTML string within the popover content function, unfortunately, the content does not display in the popover itself. Could it be due to an error in the async callback method?

Answer №1

Async calls will not function properly in this case; it is recommended to utilize the .setContent method on the popover instance instead (as an alternative, you can either create the popover after the async call or set the content as loading... and then use .setContent).

To resolve this issue, acquire the popover instance, execute your async method, and subsequently update the content:

// define the popover instance for future reference
const pop = new bootstrap.Popover(popover);

// or display 'loading' immediately
//const pop = new bootstrap.Popover(popover, {
//  content: '<p>Loading</p>'
//});


(async() => {

    var x = await SetPopoverContent();

    // update the content
    pop.setContent({
        '.popover-body': x
    })

})()

Demonstration:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c4a6ababb0b7b0b6a5b484f1eaf7eaf7">[email protected]</a>/dist/css/bootstrap.min.css" rel="stylesheet">
  <title>Bootstrap Example</title>
  <script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3f5d50504b4c4b4d5e4f7f0a110c110c">[email protected]</a>/dist/js/bootstrap.bundle.min.js"></script>
</head>

<body class="p-3 m-0 border-0 bd-example m-0 border-0">



  <button type="button" class="btn btn-lg btn-danger" data-bs-toggle="popover">Click to toggle popover</button>



  <script>
  
    function dbCall() {
      return new Promise(r => {
        setTimeout(() => r('new data'), 1000);
      })
    }

    async function SetPopoverContent() {

      let data = await dbCall();

      return data;
    }


    document.querySelectorAll('[data-bs-toggle="popover"]').forEach(function(popover) {

      const pop = new bootstrap.Popover(popover, {
        content: 'Loading'
      });

      (async() => {

        var x = await SetPopoverContent();

        pop.setContent({
          '.popover-body': x
        })
      })();

    });
  </script>

</body>

</html>

Refer to the example provided for guidance on setting content: Popovers - Methods - setContent example

The setContent method accepts an object argument, where each property-key is a valid string selector within the popover template, and each related property-value can be string | element | function | null

Answer №2

I believe this code snippet should function properly.

if (data !== null && data !== undefined) {
    var divElement = '<div></div>';
    ...
    
    contentText.innerHTML = divElement;
}
else {
    contentText.innerHTML = '<p>Loading</p>';
}

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

Potential Asynchronous Invocation within a Condition

Currently, I am in the process of restructuring some older code that was not originally written by me. A specific issue has arisen related to loading asynchronous data. When a particular modal is first activated, a significant amount of data representing a ...

To dismiss a popup on a map, simply click on any area outside the map

Whenever I interact with a map similar to Google Maps by clicking on various points, a dynamically generated popup appears. However, I am facing an issue where I want to close this popup when clicking outside the map area. Currently, the code I have writte ...

I want to create a clickable image using Vue.js

Whenever I click on the image, I aim to apply a particular class to it. Here is how I am currently trying to accomplish this: <div class="thumbnail"> <img :image_id="image.id" :src="'/storage/images/'+image.name" ...

Using useCallback with an arrow function as a prop argument

I'm having trouble understanding the code snippet below <Signup onClick={() => {}} /> Upon inspecting the Signup component, I noticed the implementation of useCallback as follows const Signup = ({onClick}) => { const handleClick = us ...

I need to show a DIV element when a specific anchor is in an active state within an HTML document

Is there a way to make the code below only visible when the url ends with #404? <!--404 code--> <style> .div1 { width: 300px; height: 100px; border: 1px solid blue; border-color: #ff0263; box-sizing: border-box; } < ...

Flex dimensions causing design elements to break in React Native

When using both import {dimension} from 'react-native' and flex:1 in a CSS style, the design may break on certain devices, especially when there is an input field present in the JavaScript. This issue is unexpected as CSS should typically be stra ...

Trouble with updating the view when an array is modified in ng-repeat? It seems like using $scope.$apply() may not

When updating the array inside a function, the view does not automatically update. However, if you use console.log to check the array after pushing values, it shows the updated array. Even trying $scope.apply() inside $timeout did not solve this issue. Ja ...

JavaScript file system function not functioning according to its designated purpose

I have a basic script to write a JavaScript list to a JavaScript file. // Using the fs module to access // the writeFile function. var fs = require('fs'); // Start by overwriting any existing file with the beginning of the list fs.writeFile(&apo ...

Is there a way to dynamically include an attribute using VueJS?

Is there a way in Vue to dynamically add an attribute, not just the value of an attribute using v-bind? I am aware that I can set a value to an attribute dynamically with v-bind, but I would like to add the attribute itself based on a condition. Something ...

Combining elements from a string array to create a hierarchical object in JavaScript

I need assistance with merging values from an array into a predefined nested object. Here is an example of the array with values, ['name=ABC XYZ', 'hobbies=[M,N,O,P]', 'profession=S', 'age=27'] The object that needs ...

Using sinon to stub a scope method called during the initialization of an angular controller

When I create a new controller, it automatically triggers a method linked to the $scope: angular.module('example', []).controller('exampleCtrl', function($scope) { $scope.method = function () { ... }; $scope.method(); }); I a ...

Error authorizing AJAX call to Gmail API

I'm just getting started with the GMail API and I'm attempting to use AJAX to fetch emails. This is my code: $.ajax({ beforeSend: function (request) { request.setRequestHeader("authorization", "Bearer xxxxxxxxxxxxxxxxx.a ...

Using PHP and AJAX to send a form

Currently, I am attempting to integrate ajax functionality into my form in order to submit it without refreshing the page. However, I have encountered an issue with the php echo command not functioning as expected. When I remove the ajax code, the form s ...

gathering information from various asynchronous functions (promises)

When faced with the need to retrieve data from multiple asynchronous functions or promises, how can you efficiently collect and persist the data so that it can be utilized once all operations are complete? An example scenario would involve executing multip ...

When checking the form action property in IE6, make sure to account for forms that have a field specifically named "action."

If I have the following form: <form id="myForm" action="index.php"> <input type="hidden" name="action" value="list" /> <input type="submit" /> </form> How do I retrieve the value of the action attribute of the form (index. ...

Could you provide an explanation for how this specific recursive JavaScript function works

This morning, while I was on codewars, I came across a Kata that required a function to reverse a string passed as a parameter using recursion. After exploring various solutions, the best one I found for this problem is shown below: function reverse(str) ...

The issue of white space appearing in the first option of an AngularJS dropdown in Internet Explorer 11

<select id="selectIdentity" name="selectIdentity" required ng-trim="true" ng-change="changedValue(addUser.identityProvider)" ng-model="addUser.identityProvider" > <option value="" selected hidden /> <option ng-repeat="idprovid ...

Issue encountered with updating canvas texture twice in A-Frame and pdf.js while operating in virtual reality mode

Using the power of A-Frame and pdf.js, I embarked on a quest to build an incredible VR application for viewing PDF files. Everything seemed to be working seamlessly on my desktop - flipping through PDF pages, rendering them onto a canvas, it was a sight to ...

Creating custom ExpectedConditions with Protractor for detecting attribute changes

I've been working on creating a custom ExpectedConditions method that can wait for an element attribute to change. Here is the approach I came up with: const CustomExpectedCondition = function() { /** * Check if element's attribute matches ...

Issue with AJAX response in Laravel 4

An interactive form on my website requires user input in the field labeled category. With each keystroke, I want to trigger an AJAX request to check if a category matching the entered name already exists. If a match is found, I intend to populate a blank d ...