rshinybslib

How to hide a bslib popover by clicking outside?


I was trying with the following example code

library(shiny)
library(bslib)

ui <- page_sidebar(
  title = "My dashboard",
  sidebar = "Sidebar",
  "Main content area",
  actionButton(
    "btn",
    "BTN"
  ) |>
    popover(
      "Popover message",
      title = "Popover title",
      selectInput(
        "test",
        "Test",
        letters[1:3],
        "a"
      ),
      options = list(trigger = "click focus")
    ),
  textOutput("text")
)

server <- function(input, output, session){
  output$text <- renderText({
    input$test
  })
}

shinyApp(ui, server)

I want to close the popover when I click outside of the popover, similar like we have in shiny modal with easyClose = TRUE.


Solution

  • Add options = list(trigger = "focus") to popover():

    library(shiny)
    library(bslib)
    
    ui <- page_sidebar(
      title = "My dashboard",
      sidebar = "Sidebar",
      "Main content area",
      actionButton(
        "btn_pop", 
        "Click here for popover"
      ) |>
        popover(
          "Popover message",
          title = "Popover title",
          options = list(trigger = "focus")
        )
    )
    
    shinyApp(ui, function(input, output) {})
    

    If the popover() contains an input (e.g. a selectInput() such as within the edited question), then we may use a JS approach as described in this answer:

    library(shiny)
    library(bslib)
    
    ui <- page_sidebar(
      tags$head(
        tags$script(
          HTML(
            "$(document).ready(function () {",
            "  $('body').on('click', function (e) {",
            "    $('[data-bs-toggle=popover]').each(function () {",
            "      if (!$(this).is(e.target) &&",
            "          $(this).has(e.target).length === 0 &&",
            "          $('.popover').has(e.target).length === 0) {",
            "        $(this).popover('hide');",
            "      }",
            "    });",
            "  });",
            "})"
          )
        )
      ),
      title = "My dashboard",
      sidebar = "Sidebar",
      "Main content area",
      actionButton(
        "btn",
        "BTN"
      ) |>
        popover(
          "Popover message",
          title = "Popover title",
          selectInput(
            "test",
            "Test",
            letters[1:3],
            "a"
          )
        ),
      textOutput("text")
    )
    
    server <- function(input, output, session){
      output$text <- renderText({
        input$test
      })
    }
    
    shinyApp(ui, server)