61

I am using bootstrap-popover to show a message beside an element.

If I want to show different text in the popover after the first time, the text does not change. Re instantiating the popover with new text does not overwrite.

See this js fiddle for a live example:

http://jsfiddle.net/RFzvp/1/

(The message in the alert and the message in the dom is inconsistent after the first click) The documentation is a bit light on how to unbind: http://twitter.github.com/bootstrap/javascript.html#popovers

Am I using this wrong? The Any suggestions on how to work around?

Thanks

12 Answers 12

82

You can access the options directly using the jquery data closure dictionary like this:

$('a#test').data('bs.popover').options.content = 'new content';

This code should work fine even after first initializing the popover.

9
  • 8
    nice one. I had to also do a $(this).popover('show'); for a popover that was already visible to update
    – periklis
    Commented Jun 30, 2013 at 7:21
  • 10
    In bootstrap 3 the namespace is changed: you have to: $('a#test').data('bs.popover').options.content = 'new content';
    – dAm2K
    Commented Feb 3, 2014 at 16:12
  • 2
    @user698585 it would have been nice if you had kept the old namespace and just added the new one. looks like BS2 simply had no namespace, so it's .data('popover'),options.content = "new content"
    – isapir
    Commented Jun 22, 2015 at 18:52
  • This is also handy but I guess when bootstrap itself allows for placing function instead of a static reference, then why using a hack?? Commented Dec 7, 2015 at 9:02
  • @Farzad YZ: What do you mean exactly? can you please suggest an alternative? Commented Dec 7, 2015 at 16:31
61

Hiya please see working demo here: http://jsfiddle.net/4g3Py/1/

I have made the changes to get your desired outcome. :)

I reckon you already know what you are doing but some example recommendations from my end as follows for sample: http://dl.dropbox.com/u/74874/test_scripts/popover/index.html# - sharing this link to give you idea for different link with different pop-over if you will see the source notice attribute data-content but what you wanted is working by the following changes.

Have a nice one and hope this helps. D'uh don't forget to up vote and accept the answer :)

Jquery Code

var i = 0;
$('a#test').click(function() {
    i += 1;

    $('a#test').popover({
        trigger: 'manual',
        placement: 'right',
        content: function() {
           var message = "Count is" + i;
             return message;
        }
    });
    $('a#test').popover("show");

});​

HTML

<a id="test">Click me</a>
​
3
  • @ThomasReggi MAGIC! I logged into SO after long time :) for this comment only, NO worries man! Glad it helped you bruv! lol
    – Tats_innit
    Commented Aug 14, 2012 at 20:45
  • Thank you it helped a lot, i had an issue with $('#search').popover('destroy'); not working, and it seem the reason was using $('#search').popover('toggle'); instead of $('#search').popover('hide'); and trigger: 'manual', however although your demo works, in my case it only worked with a $('#search').popover('destroy'); call Commented Mar 5, 2014 at 11:09
  • Note that you can't use this with a default content through data attribute, it will always take the default content.
    – Seimen
    Commented Oct 3, 2014 at 15:57
25

just in-case anyone's looking for a solution that doesn't involve re-instantiating the popover and just want to change the content html, have a look at this:

$('a#test').data('popover').$tip.find(".popover-content").html("<div>some new content yo</div>")

Update: At some point between this answer being written and Bootstrap 3.2.0 (I suspect at 3.0?) this changed a little, to:

$('a#test').data('bs.popover').tip().find ............
4
  • This helped me because I needed to update a popover during a keyup event which the top answer on this page doesn't address. Thanks!
    – 828
    Commented Feb 7, 2013 at 1:19
  • 1
    note that as soon as you close and then re-open the popup the content will still be the original one. To make sure the content will be the new one everytime the popup opens, you should also include the tip from @user698585
    – vitorbal
    Commented Mar 20, 2013 at 15:15
  • 1
    When I changed the content and then show the popover, it still showed me the original one. I changed the order. I showed the popover and then changed the content, it showed me the new one. Any idea why?
    – Sri
    Commented May 20, 2013 at 19:30
  • On BS4, I had to use : $($element.data('bs.popover').tip) to make it work Commented Apr 14, 2020 at 14:35
19

Old question, but since I notice that the no answer provides the correct way and this is a common question, I'd like to update it.

Use the $("a#test").popover("destroy");-method. Fiddle here.

This will destroy the old popover and enable you to connect a new one again the regular way.

Here's an example where you can click a button to set a new popover on an object that already has a popover attached. See fiddle for more detail.

$("button.setNewPopoverContent").on("click", function(e) {
    e.preventDefault();

    $(".popoverObject").popover("destroy").popover({
        title: "New title"
        content: "New content"
    );
});
4
  • 1
    My version of bootstrap has no "destroy" method. Perhaps it's changed?
    – medley56
    Commented Sep 11, 2017 at 19:26
  • 3
    For Bootstrap 4 use dispose method
    – Souleste
    Commented Apr 2, 2020 at 16:37
  • I get Uncaught TypeError: n.$element is null when destroying a visible popover Commented Jun 26, 2023 at 12:34
  • Check souleste's comment above, this answer is from 2014 and is no longer current. Regardless, make sure that the entire DOM and attachments have loaded before you run the snippet. It seems that your code runs before jQuery has attached the events. Commented Jun 27, 2023 at 13:05
9

The question is more than one year old, but maybe this would be usefull for others.

If the content is only changed while the popover is hidden, the easiest way I've found is using a function and a bit of JS code.

Specifically, my HTML looks like:

<input id="test" data-toggle="popover"
       data-placement="bottom" data-trigger="focus" />
<div id="popover-content" style="display: none">
  <!-- Hidden div with the popover content -->
  <p>This is the popover content</p>
</div>

Please note no data-content is specified. In JS, when the popover is created, a function is used for the content:

$('test').popover({
    html: true,
    content: function() { return $('#popover-content').html(); }
});

And now you can change anywhere the popover-content div and the popover will be updated the next time is shown:

$('#popover-content').html("<p>New content</p>");

I guess this idea will also work using plain text instead of HTML.

1
  • This actually works for me. I also had another case where I want to do something in the parent object BEFORE displaying the popover, so I just did it using a similar technique. In my case, I used an old-fashioned JS function that does all the heavy lifting, e.g. content: getDeleteMissionNodeContent. The function has a this object representing the button clicked, so I used $(this). to get that button and $(this).closest('selector') to find its parent and manipulate it. Works great. Commented Sep 18, 2018 at 19:19
5

On Boostrap 4 it is just one line:

$("#your-element").attr("data-content", "your new popover content")
2
4

You can always directly modify the DOM:

$('a#test').next(".popover").find(".popover-content").html("Content");

For example, if you want a popover that will load some data from an API and display that in the popover's content on hover:

    $("#myPopover").popover({
        trigger: 'hover'
    }).on('shown.bs.popover', function () {
        var popover = $(this);
        var contentEl = popover.next(".popover").find(".popover-content");
        // Show spinner while waiting for data to be fetched
        contentEl.html("<i class='fa fa-spinner fa-pulse fa-2x fa-fw'></i>");

        var myParameter = popover.data('api-parameter');
        $.getJSON("http://ipinfo.io/" + myParameter)
        .done(function (data) {
          var result = '';
          if (data.org) {
            result += data.org + '<br>';
          }
          if (data.city) {
            result += data.city + ', ';
          }

          if (data.region) {
            result += data.region + ' ';
          }
          if (data.country) {
            result += data.country;
          }
          if (result == '') {
            result = "No info found.";
          }
          contentEl.html(result);
        }).fail(function (data) {
          result = "No info found.";
          contentEl.html(result);
        });
    });
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<a href="#" id="myPopover" data-toggle="popover" data-title="IP Details" data-api-parameter="151.101.1.69">Hover here for details on IP 151.101.1.69</a>

This assumes that you trust the data supplied by the API. If not, you will need to escape the data returned to mitigate XSS attacks.

2
  • I like your concept @alexw; but it's not working with Bootstrap 4. Any ideas what needs to be updated? jsfiddle.net/jrcafk6w
    – Ben in CA
    Commented Oct 28, 2019 at 15:50
  • Changing line 5 to: var contentEl = $(".popover").find(".popover-body"); seems to then work for Bootstrap 4
    – Ben in CA
    Commented Oct 28, 2019 at 17:07
1

Learn't from previous answers

let popOverOptions = {
    trigger: 'click',
    ...
    };

// save popOver instance
let popOver = $(`#popover-unique-id`).popover(popOverOptions);

// get its data
let popOverData = popOver.data('bs.popover');

// load data dynamically (may be with AJAX call)
$(`#popover-unique-id`).on('shown.bs.popover', () => {

    setTimeout(() => {

        // set content, title etc...
        popOverData.config.content = 'content/////////';

        // updata the popup in realtime or else this will be shown next time opens
        popOverData.setContent();

        // Can add this if necessary for position correction: 
        popOver._popper.update();

    }, 2000);

});

This way we can update popover content easily.

There's another way using destroy method. http://jsfiddle.net/bj5ryvop/5/

0
1

Bootstrap 5.0 update

let popoverInstance = new bootstrap.Popover($('#element'));

And then:

popoverInstance._config.content = "Hello world";
popoverInstance.setContent();

(Caution: it will update popover content globally, so if you have multiple open popovers then they all will be updated with "Hello world")

1
  • Didn't even use setContent and worked, nice!
    – RamoFX
    Commented Sep 5, 2022 at 13:49
0

I found Bootstrap popover content cannot changed dynamically which introduces the setContent function. My code (hopefully helpful to someone) is therefore:

(Noting that jquery data() isn't so good at setting as it is getting)

// Update basket
current = $('#basketPopover').data('content');
newbasket = current.replace(/\d+/i,parseInt(data));

$('#basketPopover').attr('data-content',newbasket);
$('#basketPopover').setContent();
$('#basketPopover').$tip.addClass(popover.options.placement);
0

if jQuery > 4.1 use

$("#popoverId").popover("dispose").popover({
     title: "Your new title"
     content: "Your new content"
);
0

Bootstrap 5.1

I tried about 8 different ways to change the content for my Bootstrap 5.1 project, but none worked. I could see the values in the underlying popover object and could change them, but they didn't show on the page.

I got it going by first using the Bootstrap Popover's selector option, which the docs don't explain that well, but basically amounts to putting a watch on the page, so if new popover elements are added to the page (with the selector) they will become popovers automatically.

$(function() {
    // set up all popovers
    new bootstrap.Popover(document.body, {selector: 'has-popover');
})

then in my ajax call where some different content has been fetched, I remove the existing popover div, change the attribute with the text, and add it again:

var $pop = $('#pop_id1234')
var html = $pop[0].outerHTML // save the HTML
$pop.remove() 
var $new = $(html).attr('data-bs-content',popoverText) // data('bs-content') becomes bsContent which won't work
$('#pop-container').append($new)

Not the answer you're looking for? Browse other questions tagged or ask your own question.