dreamRs / shinyWidgets

shinyWidgets : Extend widgets available in shiny
https://dreamrs.github.io/shinyWidgets/
GNU General Public License v3.0
832 stars 153 forks source link

pickerInput() dropdown not working with absolutePanel & bootstrap 5 #494

Closed mark-druffel closed 2 years ago

mark-druffel commented 2 years ago

Hi there,

Thanks for this amazing package! I am experiencing an issue when I use pickerInput() inside an absolutePanel() with bootstrap 5. The dropdown does not open when I click it. I think this might be related to https://github.com/dreamRs/shinyWidgets/issues/460, but based on the latest it sounded like that had been resolved. I tested the pickerInput() using sidebarPanel and it works so it seems to be specific to absolutePanel.

When using pickerInput() inside absolute panel with bootstrap 4, the widget works as expected. absolutePanel_bs4

If I change the same code to bootstrap version 5 (line 27) the dropdown won't respond when I click it. absolutePanel_bs5

library(shiny)
library(shinyWidgets)
library(dplyr)
library(bslib)
library(reactable)
# UI ####
app_ui <- function(){
  bslib::page_navbar(
    id = "navbar",
    header = shiny::tags$style(
      HTML("
        #filtersPanel {
          padding: 0 20px 20px 20px;
          background-color: white;
          opacity: 0.65;
          zoom: 0.8;
          transition: opacity 500ms 1s;
          z-index: 9999;
        }
        #filtersPanel:hover {
          opacity: 0.95;
          transition-delay: 0;
        }"
      )
    ),
    theme = bslib::bs_theme(
      version = 5, ## CHANGE THIS TO 4 AND IT WORKS
      bootswatch = "default"
    ),
    bslib::nav(
      title = "Dashboard",
      bslib::page_fluid(
        shiny::absolutePanel(
          id = "filtersPanel",
          fixed = T,
          draggable = T,
          top = 75, left = "auto", right = 20, bottom = "auto",
          width = 330, height = "auto",
          shiny::h3("Filters"),
          shinyWidgets::pickerInput(
            inputId = "cars",
            label = "Car (picker)",
            multiple = T,
            choices = sort(rownames(mtcars)),
            selected = rownames(mtcars),
            options = shinyWidgets::pickerOptions(
              actionsBox = TRUE,
              liveSearch = T
            )
          )
        ),
        reactable::reactableOutput("tbl")
      )
    )
  )
}

# Server ####
app_server <- function(input, output, session) {
  output$tbl <- reactable::renderReactable({
    mtcars |> 
      tibble::rownames_to_column("car") |> 
      dplyr::filter(car %in% input$cars) |> 
      reactable::reactable()
  })
}

# Run ####
shiny::shinyApp(
  ui = app_ui,
  server = app_server,
  options = list(),
  enableBookmarking = NULL
)
─ Session info ────────────────────────────────────────────────────────────────────────────────────────────────
 setting  value
 version  R version 4.2.0 (2022-04-22)
 os       macOS Monterey 12.3.1
 system   x86_64, darwin17.0
 ui       RStudio
 language (EN)
 collate  en_US.UTF-8
 ctype    en_US.UTF-8
 tz       America/Los_Angeles
 date     2022-06-06
 rstudio  2022.02.2+485 Prairie Trillium (desktop)
 pandoc   2.17.1.1 @ /Applications/RStudio.app/Contents/MacOS/quarto/bin/pandoc

─ Packages ────────────────────────────────────────────────────────────────────────────────────────────────────
 package      * version    date (UTC) lib source
 assertthat     0.2.1      2019-03-21 [1] CRAN (R 4.2.0)
 bslib        * 0.3.1      2021-10-06 [1] CRAN (R 4.2.0)
 cachem         1.0.6      2021-08-19 [1] CRAN (R 4.2.0)
 cli            3.3.0      2022-04-25 [1] CRAN (R 4.2.0)
 crayon         1.5.1      2022-03-26 [1] CRAN (R 4.2.0)
 crosstalk      1.2.0      2021-11-04 [1] CRAN (R 4.2.0)
 DBI            1.1.2      2021-12-20 [1] CRAN (R 4.2.0)
 digest         0.6.29     2021-12-01 [1] CRAN (R 4.2.0)
 dplyr        * 1.0.9      2022-04-28 [1] CRAN (R 4.2.0)
 ellipsis       0.3.2      2021-04-29 [1] CRAN (R 4.2.0)
 fansi          1.0.3      2022-03-24 [1] CRAN (R 4.2.0)
 fastmap        1.1.0      2021-01-25 [1] CRAN (R 4.2.0)
 fs             1.5.2      2021-12-08 [1] CRAN (R 4.2.0)
 generics       0.1.2      2022-01-31 [1] CRAN (R 4.2.0)
 glue           1.6.2      2022-02-24 [1] CRAN (R 4.2.0)
 htmltools      0.5.2      2021-08-25 [1] CRAN (R 4.2.0)
 htmlwidgets    1.5.4      2021-09-08 [1] CRAN (R 4.2.0)
 httpuv         1.6.5      2022-01-05 [1] CRAN (R 4.2.0)
 jquerylib      0.1.4      2021-04-26 [1] CRAN (R 4.2.0)
 jsonlite       1.8.0      2022-02-22 [1] CRAN (R 4.2.0)
 later          1.3.0      2021-08-18 [1] CRAN (R 4.2.0)
 lifecycle      1.0.1      2021-09-24 [1] CRAN (R 4.2.0)
 magrittr     * 2.0.3      2022-03-30 [1] CRAN (R 4.2.0)
 mime           0.12       2021-09-28 [1] CRAN (R 4.2.0)
 pillar         1.7.0      2022-02-01 [1] CRAN (R 4.2.0)
 pkgconfig      2.0.3      2019-09-22 [1] CRAN (R 4.2.0)
 promises       1.2.0.1    2021-02-11 [1] CRAN (R 4.2.0)
 purrr          0.3.4      2020-04-17 [1] CRAN (R 4.2.0)
 R6             2.5.1      2021-08-19 [1] CRAN (R 4.2.0)
 Rcpp           1.0.8.3    2022-03-17 [1] CRAN (R 4.2.0)
 reactable    * 0.3.0      2022-05-26 [1] CRAN (R 4.2.0)
 reactR         0.4.4      2021-02-22 [1] CRAN (R 4.2.0)
 rlang          1.0.2      2022-03-04 [1] CRAN (R 4.2.0)
 rsconnect      0.8.25     2021-11-19 [1] CRAN (R 4.2.0)
 rstudioapi     0.13       2020-11-12 [1] CRAN (R 4.2.0)
 sass           0.4.1      2022-03-23 [1] CRAN (R 4.2.0)
 sessioninfo    1.2.2      2021-12-06 [1] CRAN (R 4.2.0)
 shiny        * 1.7.1      2021-10-02 [1] CRAN (R 4.2.0)
 shinyjs        2.1.0      2021-12-23 [1] CRAN (R 4.2.0)
 shinyWidgets * 0.7.0.9000 2022-06-06 [1] Github (dreamRs/shinyWidgets@0c7c858)
 tibble         3.1.7      2022-05-03 [1] CRAN (R 4.2.0)
 tidyselect     1.1.2      2022-02-21 [1] CRAN (R 4.2.0)
 utf8           1.2.2      2021-07-24 [1] CRAN (R 4.2.0)
 vctrs          0.4.1      2022-04-13 [1] CRAN (R 4.2.0)
 xtable         1.8-4      2019-04-21 [1] CRAN (R 4.2.0)
 yaml           2.3.5      2022-02-21 [1] CRAN (R 4.2.0)
obsaditelnost commented 2 years ago

Seems as if fluidPage doesn't (properly) inherit theme of navbarPage and jumps back to default (BS version < 5) at dependency check? One way to solve this as application designer would be to set theme for fuildPage as well.

However... updatePickerInput still seems to be broken:

library(shiny)
library(shinyWidgets)
library(bslib)

ui <- navbarPage(
    theme=bs_theme(version = 5, bootswatch = "default"),
    title = "example",
    tabPanel(h4("tab1"),
             fluidPage(
                 theme=bs_theme(version = 5, bootswatch = "default"),
                 sidebarLayout(
                     sidebarPanel(
                         shinyWidgets::pickerInput(
                             inputId = "cars",
                             label = "Car (picker)",
                             multiple = FALSE,
                             choices = sort(rownames(mtcars))
                         )
                     ),
                     mainPanel(verbatimTextOutput("value")) 
                 )
             ))
)

server <- function(input, output,session) {

    output$value <- renderPrint({
        input$cars
    })

    # --> broken

    # shinyWidgets::updatePickerInput(
    #     session=session,
    #     inputId = "cars",
    #     clearOptions = TRUE,
    #     choices = rownames(mtcars)
    # )
}
shinyApp(ui, server)
mark-druffel commented 2 years ago

Seems as if fluidPage doesn't (properly) inherit theme of navbarPage and jumps back to default (BS version < 5) at dependency check? One way to solve this as application designer would be to set theme for fuildPage as well.

However... updatePickerInput still seems to be broken:

library(shiny)
library(shinyWidgets)
library(bslib)

ui <- navbarPage(
    theme=bs_theme(version = 5, bootswatch = "default"),
    title = "example",
    tabPanel(h4("tab1"),
             fluidPage(
                 theme=bs_theme(version = 5, bootswatch = "default"),
                 sidebarLayout(
                     sidebarPanel(
                         shinyWidgets::pickerInput(
                             inputId = "cars",
                             label = "Car (picker)",
                             multiple = FALSE,
                             choices = sort(rownames(mtcars))
                         )
                     ),
                     mainPanel(verbatimTextOutput("value")) 
                 )
             ))
)

server <- function(input, output,session) {

    output$value <- renderPrint({
        input$cars
    })

    # --> broken

    # shinyWidgets::updatePickerInput(
    #     session=session,
    #     inputId = "cars",
    #     clearOptions = TRUE,
    #     choices = rownames(mtcars)
    # )
}
shinyApp(ui, server)

obsaditelnost I could be misunderstanding your point, but I changed my code from above to version 4 and see bs version 4 in the browser. Either way, I think my issue relates to pickerInput, not bslib, at least as far as I can tell 🤷
image

Version 4 Code:

library(shiny)
library(shinyWidgets)
library(dplyr)
library(bslib)
library(reactable)
# UI ####
app_ui <- function(){
  bslib::page_navbar(
    id = "navbar",
    header = shiny::tags$style(
      HTML("
        #filtersPanel {
          padding: 0 20px 20px 20px;
          background-color: white;
          opacity: 0.65;
          zoom: 0.8;
          transition: opacity 500ms 1s;
          z-index: 9999;
        }
        #filtersPanel:hover {
          opacity: 0.95;
          transition-delay: 0;
        }"
      )
    ),
    theme = bslib::bs_theme(
      version =4,
      bootswatch = "default"
    ),
    bslib::nav(
      title = "Dashboard",
      bslib::page_fluid(
        shiny::absolutePanel(
          id = "filtersPanel",
          fixed = T,
          draggable = T,
          top = 75, left = "auto", right = 20, bottom = "auto",
          width = 330, height = "auto",
          shiny::h3("Filters"),
          shinyWidgets::pickerInput(
            inputId = "cars",
            label = "Car (picker)",
            multiple = T,
            choices = sort(rownames(mtcars)),
            selected = rownames(mtcars),
            options = shinyWidgets::pickerOptions(
              actionsBox = TRUE,
              liveSearch = T
            )
          )
        ),
        reactable::reactableOutput("tbl")
      )
    )
  )
}

# Server ####
app_server <- function(input, output, session) {
  output$tbl <- reactable::renderReactable({
    mtcars |> 
      tibble::rownames_to_column("car") |> 
      dplyr::filter(car %in% input$cars) |> 
      reactable::reactable()
  })
}

# Run ####
shiny::shinyApp(
  ui = app_ui,
  server = app_server,
  options = list(),
  enableBookmarking = NULL
)
pvictor commented 2 years ago

Hello,

Yes I see an issue with shiny::absolutePanel() and Bootstrap 5, thanks for reporting it. I don't have a solution at the moment. Bootstrap 5 support for pickerInput() is limited for the moment (only available in beta version here : https://github.com/snapappointments/bootstrap-select/releases). An alternative could be to use virtualSelectInput() which has similar functionality.

For the second issue, you don't need fluidPage() here, xxxPage() functions shouyld only be used to initialized an UI and be used once by application. And for updatePickerInput() it should work if you install development version of shinyWidgets.

mark-druffel commented 2 years ago

@pvictor Thanks so much for the reply and all the info, I didn't realize fluidPage wasn't needed and appreciate the feedback there.

Regarding pickerInput, I had just used bootstrap 4 to make things work, but I didn't see virtualSelectInput() and agree it looks like a perfect substitute. Thanks so much for your help and for the amazing package, it's really made a huge difference for my app!