I am trying to create a simple application where the sidebar will change depending on which tabsetPanel the user is currently selecting. It works with R Shiny natively but when I try and style it with bslib, it starts breaking. I suspect it is a result of some Javascript or NS conflicts.
Additionally, it only breaks when I use versions 4 or 5 of Bootswatch themes. I have provided a minimal example below.
Why does the conditionalPanel with textInput id = "textInput2"
not show up? If you change the version of bootswatch back to version 3, it works.
library(shiny)
library(bslib)
options(shiny.port = 8080)
# UI/Server for Module_1
module_1_ui <- function(id) {
ns <- NS(id)
tabPanel("Main", fluid = TRUE,
sidebarLayout(
sidebarPanel(
textInput(ns('textInput'), 'Enter text')
),
mainPanel(
uiOutput(ns('textOutput'))
)
)
)
}
module_1_server <- function(id, session) {
moduleServer(id, function(input, output, session) {
ns <- session$ns
output$textOutput <- renderUI({
req(input$textInput)
HTML(paste0('You entered: ', input$textInput))
})
})
}
# UI/Server for Module_2
module_2_ui <- function(id) {
ns <- NS(id)
tabPanel("Side", fluid = TRUE,
sidebarLayout(
sidebarPanel(
HTML("This always shows!"),
br(),
conditionalPanel(
condition = sprintf("input['%s'] == 'Test2'", ns("side_tabsets")),
textInput(ns('textInput2'), 'Enter text')
)
),
mainPanel(
uiOutput(ns('sideOutput'))
)
)
)
}
module_2_server <- function(id, session) {
moduleServer(id, function(input, output, session) {
ns <- session$ns
output$sideOutput <- renderUI({
tabsetPanel(
id = ns("side_tabsets"),
tabPanel(title = "Test1", br(), actionButton(ns("button1"), "Button 1")),
tabPanel(title = "Test2", br(), actionButton(ns("button2"), "Button 2"))
)
})
})
}
# Overall UI
ui <- fluidPage(
theme = bs_theme(bootswatch = "cosmo", version = 5),
navbarPage(title = "",
module_1_ui("main"),
module_2_ui("side")
)
)
# Overall Server
server <- function(input, output, session) {
module_1_server("main", session)
module_2_server("side", session)
}
shinyApp(ui = ui, server = server)
Here is my sessionInfo:
> sessionInfo()
R version 4.3.3 (2024-02-29)
Platform: x86_64-apple-darwin20 (64-bit)
Running under: macOS Sonoma 14.3.1
Matrix products: default
BLAS: /Library/Frameworks/R.framework/Versions/4.3-x86_64/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-x86_64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
time zone: America/Los_Angeles
tzcode source: internal
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] bslib_0.8.0 shiny_1.8.1.1
loaded via a namespace (and not attached):
[1] digest_0.6.36 later_1.3.2 R6_2.5.1 httpuv_1.6.15
[5] fastmap_1.2.0 magrittr_2.0.3 cachem_1.1.0 htmltools_0.5.8.1
[9] lifecycle_1.0.4 promises_1.3.0 cli_3.6.3 xtable_1.8-4
[13] sass_0.4.9 jquerylib_0.1.4 compiler_4.3.3 tools_4.3.3
[17] mime_0.12 Rcpp_1.0.13 jsonlite_1.8.8 rlang_1.1.4
I have tried redownloading shiny and bslib to see if it was a problem with the package installation.
bslib
has its own page_*
functions for generating page layouts which should be used in favor of shiny's *Page
functions. Replace fluidPage()
and navbarPage()
with page_fluid()
and page_navbar()
and it will work.
library(shiny)
library(bslib)
options(shiny.port = 8080)
# UI/Server for Module_1
module_1_ui <- function(id) {
ns <- NS(id)
tabPanel("Main", fluid = TRUE,
sidebarLayout(
sidebarPanel(
textInput(ns('textInput'), 'Enter text')
),
mainPanel(
uiOutput(ns('textOutput'))
)
)
)
}
module_1_server <- function(id, session) {
moduleServer(id, function(input, output, session) {
ns <- session$ns
output$textOutput <- renderUI({
req(input$textInput)
HTML(paste0('You entered: ', input$textInput))
})
})
}
# UI/Server for Module_2
module_2_ui <- function(id) {
ns <- NS(id)
tabPanel("Side", fluid = TRUE,
sidebarLayout(
sidebarPanel(
HTML("This always shows!"),
br(),
conditionalPanel(
condition = sprintf("input['%s'] == 'Test2'", ns("side_tabsets")),
textInput(ns('textInput2'), 'Enter text')
)
),
mainPanel(
uiOutput(ns('sideOutput'))
)
)
)
}
module_2_server <- function(id, session) {
moduleServer(id, function(input, output, session) {
ns <- session$ns
output$sideOutput <- renderUI({
tabsetPanel(
id = ns("side_tabsets"),
tabPanel(title = "Test1", br(), actionButton(ns("button1"), "Button 1")),
tabPanel(title = "Test2", br(), actionButton(ns("button2"), "Button 2"))
)
})
})
}
# Overall UI
ui <- page_fluid(
theme = bs_theme(bootswatch = "cosmo", version = 5),
page_navbar(title = "",
module_1_ui("main"),
module_2_ui("side")
)
)
# Overall Server
server <- function(input, output, session) {
module_1_server("main", session)
module_2_server("side", session)
}
shinyApp(ui = ui, server = server)