How to use Stimulus inside Bootstrap's popovers?

Is it possible to have Stimulus actions triggered inside Bootstrap popovers’ elements?

In the example below (html + Stimulus contoller), clicking on a button prints ‘FOO’ in the console, except when this button appears in a popup.
I understand showing the popover dynamically changes the DOM (see ‘content: function…’ below).

If it’s not possible, how can Stimulus code be called from plain javascript:

   .. onclick="$('#controller_div').<trigger the "foo" action on the associated controller ???>" ..
import {Controller} from 'stimulus'

export default class extends Controller {
    foo() {console.log('FOO')}
}
<h3>Bootstrap 4 Popover & Stimulus</h3>
<p>Check the JS console for messages ("FOO")</p>
<div id="sandbox">
  <div id="controller_div" data-controller="foobar">
    <a data-action="foobar#foo" id="example_1" data-toggle="popover" href="">Show the popover</a>
    <br>
    <button data-action="foobar#foo">Some clickable button (SUCCESS)</button>
    
    <div id="popover-content-example_1" class="d-none">
      <button data-action="foobar#foo">Some clickable button (FAIL)</button>
    </div>
  </div>
</div>

<script>
    document.addEventListener("turbolinks:load", function () {
        $("[data-toggle='popover']").each(function () {
            $(this).popover({
                html: true,
                trigger: 'focus',
                content: function () {
                    var id = $(this).attr('id')
                    return $('#popover-content-' + id).html();
                }
            });
        }).click(function (e) {
            e.preventDefault();
        }).mouseenter(function (e) {
            // $(this).popover('show');
        });
    })
</script>

If nothing else works, I’ve found an ugly hack via onclick:

Replace

  <div data-controller="foobar">
    <div id="popover-content-example_1" class="d-none">
      <button data-action="foobar#foo" >Some clickable button (FAIL)</button>
              ^^^^^^^^^^^^^^^^^^^^^^^
                   DOES NOT WORK
  <div id="controller_div" 
       data-controller="foobar" data-action="foo->foobar#foo"
  > //                                      ^^^^^^^^^^^^^^^^^
    <div id="popover-content-example_1" class="d-none">
      <button onclick="document.getElementById('controller_div').dispatchEvent(new Event('foo'));"
              ^^^^^^^^^^^^^^^^^
                DOES WORK
      >Some clickable button (FAIL)</button>

I faced one issue integrating select2 and problem was - select2 is not firing native events. May be here is the same thing.
My workaround was:

.on('select2:select', function() {
  let event = new Event('change', { bubbles: true })
  element.dispatchEvent(event)
})

I didn’t use change because re-firing native change on jquery change lead to infinite circular firing.

If your problem is the same - I can suggest here is to start listen for event on connect()

4 Likes

Thanks! This was a livesaver!