Adrian Mojica
Adrian Mojica

Reputation: 4053

HTML inside Twitter Bootstrap popover

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>

Upvotes: 321

Views: 452327

Answers (15)

rehan aziz
rehan aziz

Reputation: 64

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>

Upvotes: 0

loopasam
loopasam

Reputation: 3136

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

Upvotes: 7

Daniel Donnelly
Daniel Donnelly

Reputation: 610

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

Upvotes: 0

Sahil Jain
Sahil Jain

Reputation: 89

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 })

Upvotes: 5

Mauno V&#228;h&#228;
Mauno V&#228;h&#228;

Reputation: 9788

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.

Upvotes: 377

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>

Upvotes: 0

Tiago Piovesan
Tiago Piovesan

Reputation: 121

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

Upvotes: 11

Jack
Jack

Reputation: 2771

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/

Upvotes: 123

Tomas Ramirez Sarduy
Tomas Ramirez Sarduy

Reputation: 17471

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/

Upvotes: 9

Marc A
Marc A

Reputation: 711

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();
        }
    });
});

Upvotes: 7

Guy Biber
Guy Biber

Reputation: 150

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.

Upvotes: 2

user1079877
user1079877

Reputation: 9358

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});

Upvotes: 4

user3319310
user3319310

Reputation: 251

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>'>

Upvotes: 25

Dennis M&#252;nkle
Dennis M&#252;nkle

Reputation: 5071

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>

Upvotes: 303

Mike Lucid
Mike Lucid

Reputation: 1354

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 });

Upvotes: 88

Related Questions