316

I am trying to display HTML inside a bootstrap popover, but somehow it's not working. I found some answers here but it won't work for me. Please let me know if I'm doing something wrong.

<script>
  $(function(){
    $('[rel=popover]').popover({ 
      html : true, 
      content: function() {
        return $('#popover_content_wrapper').html();
      }
    });
  });
</script>

<li href="#" id="example" rel="popover" data-content="" data-original-title="A Title"> 
    popover
</li>

<div id="popover_content_wrapper" style="display: none">
    <div>This is your div content</div>
</div>
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Adrian Mojica
  • 3,993
  • 4
  • 17
  • 20
  • 1
    I answered at the same quesion here: [Code for normalization bootstrap popovers: multiply popovers, close button, close outside the popover, and popover with custom HTML.](http://stackoverflow.com/questions/33635046/bootstrap-3-popover-div-html) – Olga Nov 11 '15 at 09:35

15 Answers15

373

You cannot use <li href="#" since it belongs to <a href="#" that's why it wasn't working, change it and it's all good.

Here is working JSFiddle which shows you how to create bootstrap popover.

Relevant parts of the code is below:

HTML:

<!-- 
Note: Popover content is read from "data-content" and "title" tags.
-->
<a tabindex="0"
   class="btn btn-lg btn-primary" 
   role="button" 
   data-html="true" 
   data-toggle="popover" 
   data-trigger="focus" 
   title="<b>Example popover</b> - title" 
   data-content="<div><b>Example popover</b> - content</div>">Example popover</a>

JavaScript:

$(function(){
    // Enables popover
    $("[data-toggle=popover]").popover();
});

And by the way, you always need at least $("[data-toggle=popover]").popover(); to enable the popover. But in place of data-toggle="popover" you can also use id="my-popover" or class="my-popover". Just remember to enable them using e.g: $("#my-popover").popover(); in those cases.

Here is the link to the complete spec: Bootstrap Popover

Bonus:

If for some reason you don't like or cannot read content of a popup from the data-content and title tags. You can also use e.g. hidden divs and a bit more JavaScript. Here is an example about that.

Mauno Vähä
  • 9,688
  • 3
  • 33
  • 54
301

you can use attribute data-html="true":

<a href="#" id="example"  rel="popover" 
    data-content="<div>This <b>is</b> your div content</div>" 
    data-html="true" data-original-title="A Title">popover</a>
denis.peplin
  • 9,585
  • 3
  • 48
  • 55
Dennis Münkle
  • 5,036
  • 1
  • 19
  • 18
  • Is there a way to use it in gwtbootstrap3, it doesn't work in this form. I've asked the question here http://stackoverflow.com/questions/34142815/how-to-enable-html-in-popover-or-tooltip-in-gwtbootstrap3, but no answer so far. – Ivan Bilan Dec 07 '15 at 21:54
  • Don't know why the above answer is marked as correct. Maybe people deliberately choose the most complicated option to preserve their jobs. – tread Apr 16 '16 at 12:33
  • I have this popover at the bottom of my page and works great except... It shifts me all the way back to the top of the page. I have it set in a foreach loop of bootstrap thumbnails. Any ideas? – foxtangocharlie Feb 17 '17 at 18:32
120

Another way to specify the popover content in a reusable way is to create a new data attribute like data-popover-content and use it like this:

HTML:

<!-- Popover #1 -->
<a class="btn btn-primary" data-placement="top" data-popover-content="#a1" data-toggle="popover" data-trigger="focus" href="#" tabindex="0">Popover Example</a>

<!-- Content for Popover #1 -->
<div class="hidden" id="a1">
  <div class="popover-heading">
    This is the heading for #1
  </div>

  <div class="popover-body">
    This is the body for #1
  </div>
</div>

JS:

$(function(){
    $("[data-toggle=popover]").popover({
        html : true,
        content: function() {
          var content = $(this).attr("data-popover-content");
          return $(content).children(".popover-body").html();
        },
        title: function() {
          var title = $(this).attr("data-popover-content");
          return $(title).children(".popover-heading").html();
        }
    });
});

This can be useful when you have a lot of html to place into your popovers.

Here is an example fiddle: http://jsfiddle.net/z824fn6b/

T J
  • 42,762
  • 13
  • 83
  • 138
Jack
  • 2,741
  • 2
  • 24
  • 32
87

You need to create a popover instance that has the html option enabled (place this in your javascript file after the popover JS code):

$('.popover-with-html').popover({ html : true });

Mike Lucid
  • 1,344
  • 13
  • 26
25

I used a pop over inside a list, Im giving an example via HTML

<a type="button" data-container="body" data-toggle="popover" data-html="true" data-placement="right" data-content='<ul class="nav"><li><a href="#">hola</li><li><a href="#">hola2</li></ul>'>
user3319310
  • 251
  • 3
  • 2
11

You only need put data-html="true" in the link popover. Is gonna work.

Tiago Piovesan
  • 121
  • 1
  • 3
9

This is an old question, but this is another way, using jQuery to reuse the popover and to keep using the original bootstrap data attributes to make it more semantic:

The link

<a href="#" rel="popover" data-trigger="focus" data-popover-content="#popover">
   Show it!
</a>

Custom content to show

<!-- Let's show the Bootstrap nav on the popover-->
<div id="list-popover" class="hide">
    <ul class="nav nav-pills nav-stacked">
        <li><a href="#">Action</a></li>
        <li><a href="#">Another action</a></li>
        <li><a href="#">Something else here</a></li>
        <li><a href="#">Separated link</a></li>
    </ul>
</div>

Javascript

$('[rel="popover"]').popover({
    container: 'body',
    html: true,
    content: function () {
        var clone = $($(this).data('popover-content')).clone(true).removeClass('hide');
        return clone;
    }
});

Fiddle with complete example: http://jsfiddle.net/tomsarduy/262w45L5/

Community
  • 1
  • 1
Tomas Ramirez Sarduy
  • 17,294
  • 8
  • 69
  • 85
7

This is a slight modification on Jack's excellent answer.

The following makes sure simple popovers, without HTML content, remain unaffected.

JavaScript:

$(function(){
    $('[data-toggle=popover]:not([data-popover-content])').popover();
    $('[data-toggle=popover][data-popover-content]').popover({
        html : true,
        content: function() {
          var content = $(this).attr("data-popover-content");
          return $(content).children(".popover-body").html();
        },
        title: function() {
          var title = $(this).attr("data-popover-content");
          return $(title).children(".popover-heading").html();
        }
    });
});
Community
  • 1
  • 1
Marc A
  • 671
  • 1
  • 8
  • 12
5

On the latest version of bootstrap 4.6, you might also need to use sanitize:false for adding complex html.

$('.popover-with-html').popover({ html : true, sanitize : false })
Sahil Jain
  • 89
  • 1
  • 6
4

I really hate to put long HTML inside of the attribute, here is my solution, clear and simple (replace ? with whatever you want):

<a class="btn-lg popover-dismiss" data-placement="bottom" data-toggle="popover" title="Help">
    <h2>Some title</h2>
    Some text
</a>

then

var help = $('.popover-dismiss');
help.attr('data-content', help.html()).text(' ? ').popover({trigger: 'hover', html: true});
user1079877
  • 9,008
  • 4
  • 43
  • 54
4

For Bootstrap >= 5.2

To enable HTML content in Popovers: data-bs-html="true"

Example:

<a href="#"
  data-bs-toggle="popover"
  data-bs-title="A Title"
  data-bs-html="true"
  data-bs-content="This is <strong>bold</strong>">popover</a>

Doc: https://getbootstrap.com/docs/5.3/components/popovers/#options

loopasam
  • 3,027
  • 2
  • 21
  • 22
2

You can change the 'template/popover/popover.html' in file 'ui-bootstrap-tpls-0.11.0.js' Write: "bind-html-unsafe" instead of "ng-bind"

It will show all popover with html. *its unsafe html. Use only if you trust the html.

Guy Biber
  • 150
  • 2
  • 6
0

You can use the popover event, and control the width by attribute 'data-width'

$('[data-toggle="popover-huongdan"]').popover({ html: true });
$('[data-toggle="popover-huongdan"]').on("shown.bs.popover", function () {
    var width = $(this).attr("data-width") == undefined ? 276 : parseInt($(this).attr("data-width"));
    $("div[id^=popover]").css("max-width", width);
});
 <a class="position-absolute" href="javascript:void(0);" data-toggle="popover-huongdan" data-trigger="hover" data-width="500" title="title-popover" data-content="html-content-code">
 <i class="far fa-question-circle"></i>
 </a>
0

Actually if you're using Bootstrap5 with Django then their method of passing in content as a string is perfect and in line with Django's template inclusion. You can create a template file with whatever partial HTML that you need, so for example, there is not X-editable for Bootstrap5 that seems to work, so maybe you'd want to make a line edit together with Ok|Cancel buttons as content. Anyway, this is what I mean:

 <button data-bs-content="{% include './popover_content.html' %}" type="button" class="btn btn-lg btn-danger" data-bs-toggle="popover" title="Popover title" >
  Click to toggle popover
 </button>

Where my settings.py templates section looks like this:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],
        'APP_DIRS': True,     # True is necessary for django-bootstrap5 to work!
        'OPTIONS': {
            'debug': True,
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

I keep my templates (of every single app) in a <project dir>/templates/<app name> folder. I have MyMainApp/popover_content.html right beside MyMainApp/home.html wher the above example code was tested. But if you keep your templates in each app's Django folder, then you'll need to add "MyApp/templates" to the TEMPLATES[0]{'DIRS': ['MyApp/templates', 'MyApp2/templates']} list.

So at least this will give you the ability to put your popover HTML in the usual, syntax-highlighted Django template format, and makes good use of modularizaton of your Django template into components.

I'm personally going to use it to make an editable label (title and description fields of some data in my app).

One drawback is that if you use doublequotes (") when including: "{% include './popover_content.html' %}", then you must use single quotes all throughout the popover_content.html` template.

You also need to enable html for popovers, so your site-wide popover initializer would go:

<script type="text/javascript">
  $(document).ready(() => {
    var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
    var popoverList = popoverTriggerList.map(
      function (popoverTriggerEl) {
        return new bootstrap.Popover(popoverTriggerEl, {
          html: true,
        });
      });
  });
</script>

Here is the (unstyled) result. In conclusion, use the default-provided string method of passing in, and pass in an included Django template file. Problem solved!

enter image description here

MathCrackExchange
  • 595
  • 1
  • 6
  • 25
0

To ensure that your popover remains open when hovering over its content, you need to manually trigger the popover event. This entails creating your own event listeners for mouse enter and mouse leave actions.

var counter;
$('[rel="popover"]').popover({
        container: 'body',
        html: true,
        trigger: 'manual',
        content: function () {
            var html = $($(this).data('popover-content')).html();
            return html;
        }
    }).on("mouseenter", function(e) {
        var _this = this;
        e.preventDefault();
        clearTimeout(counter);
        $('[rel="popover"]').not(_this).popover('hide');
        counter = setTimeout(function(){
            if($(_this).is(':hover'))
            {
                $(_this).popover("show");
            }
            $(".popover").on("mouseleave", function () {
                $(_this).popover('hide');
            });
        }, 400);
        
    }).on("mouseleave", function () {
        var _this = this;

        setTimeout(function () {
            if (!$(".popover:hover").length) {
                if(!$(_this).is(':hover')) // change $(this) to $(_this) 
                {
                   $(_this).popover('hide');
                }
            }
        }, 200);
    });
a[rel="popover"]{
    display: inline-block;
    margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<a href="#" rel="popover" data-trigger="focus" data-popover-content="#list-popover">Show Popover</a>
<a href="#" rel="popover" data-trigger="focus" data-popover-content="#list-popover">Show Popover</a>
<a href="#" rel="popover" data-trigger="focus" data-popover-content="#list-popover">Show Popover</a>

<div id="list-popover" class="hide">
  <ul class="nav nav-pills nav-stacked">
    <li><a href="#">Action</a></li>
    <li><a href="#">Another action</a></li>
    <li><a href="#">Something else here</a></li>
    <li><a href="#">Separated link</a></li>
  </ul>
</div>
<div id="output">
<div>
rehan aziz
  • 64
  • 1
  • 8