skip to Main Content

When I create a brand new Rails 7 app with Bootstrap, Modals work out of the box but Popovers don’t. How do I get them to work?

Rails 7.1.2, esbuild, Bootstrap 5.3.2:

rails new --database sqlite3 --javascript esbuild --css bootstrap bootstrap_test
cd bootstrap_test
bin/setup
rails g scaffold page
edit app/views/pages/index.html.erb #see below
bin/dev
#app/views/pages/index.html.erb
<h1 class="display-1">Hello Bootstrap</h1>

<div class="modal fade" id="exampleModalXl" tabindex="-1" aria-labelledby="exampleModalXlLabel" style="display: none;" aria-hidden="true">
  <div class="modal-dialog modal-xl">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-4" id="exampleModalXlLabel">If you can see this...</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        Modals are working 🎉
      </div>
    </div>
  </div>
</div>


<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModalXl">Modal test</button>
<br>
<button type="button" class="btn btn-danger" data-bs-toggle="popover" data-bs-title="If you can see this..." data-bs-content="Popovers are working 🎉">Popover test</button>

According to the Bootstrap docs:

Popovers are opt-in for performance reasons, so you must initialize them yourself.

I tried putting their suggested initialisation code in but I get a ReferenceError: Can't find variable: bootstrap:

console.log('Loading popovers...')

const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))

At one point I tried initialising them via Stimulus but I couldn’t get that working either.

Am I missing something obvious?

2

Answers


  1. Chosen as BEST ANSWER

    After posting my question I found a similar/related question which helped me find a solution.

    To reference bootstrap from a JS file within my app, I duplicated the import * as bootstrap from "bootstrap" command from the main application.js file...

    //app/javascript/popovers.js
    
    console.log('Loading popovers...')
    
    import * as bootstrap from "bootstrap"
    
    const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
    const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
    

    Then I imported that file from my main application.js:

    //app/javascript/application.js
    
    // Entry point for the build script in your package.json
    import "@hotwired/turbo-rails"
    import "./controllers"
    import * as bootstrap from "bootstrap"
    import "./popovers.js"
    

    Now popovers and modals are both displaying. I just have to figure out how to dismiss the popovers when I click somewhere else in the document 🤔

    Popovers working... but obscuring a modal


  2. Here’s what I think is best practice. It assumes you have a rails 7.1 app with esbuild and bootstrap. It could be created via:

    rails new myapp --css=bootstrap
    

    Add popover (example taken from bootstrap 5.3 docs) to a view (so we’ll be able to click on it to confirm that it works):

    <button type="button" class="btn btn-lg btn-danger" data-bs-toggle="popover" 
    data-bs-title="Popover title" 
    data-bs-content="And here's some amazing content. It's very engaging. Right?">
    Click to toggle popover</button>
    

    And copy/paste these 2 lines to the bottom of app/javascript/application.js:

    const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
    const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
    

    Start the rails server with bin/dev, and click on the button to see the popover appear:

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search