bootstrap 5 popover with html content

Viewed 11889

I am trying to get separate the bootstrap5 popover content from the HTML attributes like you can do with other components, but I can't get it to work.

var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
var popoverList = popoverTriggerList.map(function(popoverTriggerEl) {
  return new bootstrap.Popover(popoverTriggerEl)
})
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">

<a type="button" class="btn btn-lg btn-danger" data-bs-toggle="popover">Click to toggle popover</a>
<div id="customdiv" style="display: none">
  <h1> popover </h1>
</div>

<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.1/dist/umd/popper.min.js" integrity="sha384-SR1sx49pcuLnqZUnnPwx6FCym0wLsk5JZuNx2bPPENzswTNFaQU1RDvt3wT4gWFG" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.min.js" integrity="sha384-j0CNLUeiqtyaRmlzUHCPZ+Gy5fQu0dQ6eZ/xAww941Ai1SxSY+0EQqNXNE6DZiVc" crossorigin="anonymous"></script>

10 Answers
var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
    return new bootstrap.Popover(popoverTriggerEl,{html: true})
});

Nobody answered properly with simple JavaScript without jQuery dependency. It's important because Bootstrap 5 doesn't depend on jQuery anymore.

HTML:

<a class="btn btn-link" data-bs-toggle="popover" data-bs-placement="bottom" data-bs-content-id="popover-content" tabindex="0" role="button">
  Open Popover
</a>

<div id="popover-content" class="d-none">
  Popover content with <strong>HTML</strong>.
</div>

JavaScript:

const list = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
list.map((el) => {
  let opts = {
    animation: false,
  }
  if (el.hasAttribute('data-bs-content-id')) {
    opts.content = document.getElementById(el.getAttribute('data-bs-content-id')).innerHTML;
    opts.html = true;
  }
  new bootstrap.Popover(el, opts);
})

None of the answers really offered me a complete solution where the popover does not appear until the data-bs-trigger event happen so this is my solution:

Element that when hovering on will have popover:

<a class="btn btn-question-tag" 
   data-bs-toggle="popover" 
   data-bs-trigger="hover focus" 
   data-content-id="popover-27" 
   href="#">
element to trigger popover
</a>

Element that its inner html will be in the popover that appears.

<div style="display: none;" id="popover-27">
    <div class="popover" role="tooltip">
      This is the 
    </div>
</div>

javascript:

var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'));
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
    const popoverId = popoverTriggerEl.attributes['data-content-id'];
    if (popoverId) {
        const contentEl=$(`#${popoverId.value}`).html();
        return new bootstrap.Popover(popoverTriggerEl, {
            content: contentEl,
            html: true,
        });
    }else{//do something else cause data-content-id isn't there.
    }
}

There is a simple way to put an html element in popover container

you must put the html element directly in data-bs-content tag, and set the data-bs-html="true" to parse that content as html and also disable the sanitize to make the content readable as html

this code works for me try it too.

var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
var popoverList = popoverTriggerList.map(function(popoverTriggerEl) {
  return new bootstrap.Popover(popoverTriggerEl)
})
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">

<a type="button" class="btn btn-lg btn-danger" data-bs-toggle="popover"
data-bs-html="true" data-bs-sanitize="false"
data-bs-content='<div class="popover fs-6" role="tooltip">
 <div class="popover-body">Providing your birthday helps make sure you get the right Facebook experience for your age. If you want to change who sees this, go to the About section of your profile. For more details, please visit our <a href="#"> Data Policy</a>.</div></div>'>Click to toggle popover</a>


<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.1/dist/umd/popper.min.js" integrity="sha384-SR1sx49pcuLnqZUnnPwx6FCym0wLsk5JZuNx2bPPENzswTNFaQU1RDvt3wT4gWFG" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.min.js" integrity="sha384-j0CNLUeiqtyaRmlzUHCPZ+Gy5fQu0dQ6eZ/xAww941Ai1SxSY+0EQqNXNE6DZiVc" crossorigin="anonymous"></script>

var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
  return new bootstrap.Popover(popoverTriggerEl)
})
var popover = new bootstrap.Popover(document.querySelector('.element'), {
        trigger: 'hover',
        html: true,
        content:function () {
            return '<label>Test</label>';
        },
})

Bootstrap v5.2.0 and laravel 8 in app.js

document.addEventListener('DOMContentLoaded', function() {
 var element = document.getElementById('myPopover');
 if (element) {
     var popover = new bootstrap.Popover(element, {
         container: 'body',
         html: true,
         content: function() {
             return document.getElementById('popover-content').innerHTML;
         },
     });
 }
});

Laravel blade

                  <a tabindex="0" type="button" data-bs-toggle="popover" data-bs-placement="bottom" aria-label="Share this article socially" id="myPopover" >
                                   <img src="{{asset('layout/icon_return.svg')}}" alt="share icon">
                               </a>
   
   
                               <div class="pop-in" id="popover-content" style="display:none;"> <div class="btn-toolbar" role="toolbar" aria-label="Toolbar with button groups">
                                       <div class="btn-group" role="group" aria-label="First group">
                                           <a class="btn btn-secondary" href="https://www.facebook.com/sharer.php?u={{ $item->url }}" target="_blank" rel="noopener" type="button" ><img src="{{asset('layout/facebook.svg')}}" alt="Share Page on Facebook" ></a>
                                           <a class="btn btn-secondary" href="https://twitter.com/intent/tweet?url={{ $item->url }}%2F&text={{ $item->title }}.&hashtags=css,html" target="_blank" rel="noopener" type="button" ><img src="{{asset('layout/twitter.svg')}}" alt="Share Page on Twitter"></a>
                                           <a class="btn btn-secondary" href="https://www.linkedin.com/shareArticle?mini=true&url={{ $item->url }}%2F&item={{ $item->title }}" target="_blank" rel="noopener" type="button" ><img src="{{asset('layout/linkedin.svg')}}" alt="Share Page on LinkedIn" ></a>
                                       </div>
                                   </div>
                               </div>

Although the above answers looks fine but there is small correction here. Content option in bootstrap 5 is not working with innerHTML as it expects the type element/string/function to get the content from.

So as usual, first we will need to create div for the content with some id and then wrap it inside hidden div as this will be also shown in main flow. And then with html and content options provided by bootstrap popover, we will insert the custom popover content.

Also, instead of innerHTML, we will directly have document.getElementById('mypopover-content') as the popover content element to show as the content (and not document.getElementById('mypopover-content').innerHTML).

var popover = new bootstrap.Popover(document.querySelector('.example-popover'), {
  container: 'body',
  html: true,
  content: document.getElementById('mypopover-content'),
})
body {
margin: 10px !important;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js"></script>


<a class="btn btn-primary example-popover" role="button" tabindex="0"  title="Content demonstration popover"
>Trigger popover with other html content</a>

<div hidden>
  <div id="mypopover-content">
    <p>This is the custom popover html content that should be inserted into my example popover</p>
    <button type="button" class="btn btn-primary">and the button as well</button>
  </div>
</div>

$(function() {
var options = {
    html: true,
    title: "Optional: HELLO(Will overide the default-the inline title)",
    //html element
    content: $("#popover-content")
    //Doing below won't work. Shows title only
    //content: $("#popover-content").html()

  }
  var exampleEl = document.getElementById('example')
  var popover = new bootstrap.Popover(exampleEl, options)
})
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ" crossorigin="anonymous"></script>

<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>


<div id="popover-content">
  <div class="input-group">
    <input type="text" class="form-control form-control-sm" placeholder="Search" name="search">
    <div class="input-group-btn">
      <button class="btn btn-danger" type="submit">
        <i class="bi bi-search"></i>
      </button>
    </div>
  </div>
  <div class="col-sm-8"></div>
  <button class="btn btn-success m-3">Button</button>
  <input type="submit" class="btn btn-danger" placeholder="Button red">
</div>

<a id="example" tabindex="0" class="btn btn-lg btn-danger" role="button" data-bs-toggle="popover" title="Default: Html inside popover" data-bs-content="And here's some amazing content. It's very engaging. Right? This is default, but Can be empty">Html inside popover</a>

var hideDiv = document.getElementsByClassName('hide')[0].style.visibility = 'hidden'
var popoverBtn = document.getElementById('btn-action')
var popover = new bootstrap.Popover(popoverBtn, {
    placement: 'bottom',
    html: true,
    content: function() {
        return document.getElementById('id-content-div');
    }

})
   var showDiv = document.getElementsByClassName('hide')[0].style.visibility = 'visible'
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">

<a type="button" class="btn btn-lg btn-danger" id="btn-action">Click to toggle popover</a>
<div id="id-content-div" class="hide">
  <h1> popover </h1>
  <p>Hello popover world</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.1/dist/umd/popper.min.js" integrity="sha384-SR1sx49pcuLnqZUnnPwx6FCym0wLsk5JZuNx2bPPENzswTNFaQU1RDvt3wT4gWFG" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.min.js" integrity="sha384-j0CNLUeiqtyaRmlzUHCPZ+Gy5fQu0dQ6eZ/xAww941Ai1SxSY+0EQqNXNE6DZiVc" crossorigin="anonymous"></script>

You can't have a zero length title and content. From the Bootstrap docs...

"Zero-length title and content values will never show a popover."

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

Demo

Related