EDIT: The author of the bs4Dash
package, David Granjon, recently provided an answer to the question asked in the Github issue referenced below and closed it.
bs4Dash
github repo, but no answer was provided there.I am making a modularized Shiny application and am attempting to do it with the bs4Dash
package. This is what the application looks like:
Picture 1
The end application has several sections (I only made the Introduction for this example) and each section contains at least one bs4TabCard
. The tabcard in the picture above has one uiOutput
and one rhandsontableOutput
element, which are rendered in the server function. Note that these are both ***Output
elements. In the reproducible code for Picture 1 (which you can find at the end of the question), I do not use any module. However, my goal is to use several modules because the application has the potential to become quite large. For this simple example, I try to use two modules: one module for each section (i.e. each bs4TabItem
) and one module for each tabcard. This means that the two modules will invariably be nested: the tabcard module will be inside the section module.
Picture 2
The issue is that when I implement the modules, the ***Output
elements are not displayed:
Picture 3
The surprising thing is that ***Input
elements are displayed. I made a third module containing a numericInput
only and placed it in the second tab of the tabcard. The picture below shows that the numericInput
is displayed with no problem:
Picture 4
In this issue, a similar problem is reported, but there has not been any solution offered and my digging around proved unsuccessful. It seems that there is a problem when an output element is placed deep inside several nested containers in bs4Dash
.
Reproducible code for picture 1
library(shiny)
library(bs4Dash)
library(rhandsontable)
shiny::shinyApp(
ui = bs4DashPage(
old_school = FALSE,
sidebar_min = TRUE,
sidebar_collapsed = FALSE,
controlbar_collapsed = FALSE,
controlbar_overlay = TRUE,
title = "Basic Dashboard",
navbar = bs4DashNavbar(),
sidebar = bs4DashSidebar(
sidebarMenu(
bs4Dash::menuItem(
text = "Introduction",
tabName = "tab-introduction",
icon = ""
)
)
),
controlbar = bs4DashControlbar(),
footer = bs4DashFooter(),
body = bs4DashBody(
bs4TabItems(
bs4TabItem(
tabName = "tab-introduction",
bs4TabCard(
id = "tabcard", title = "Tab Card", side = "right",
bs4TabPanel(
tabName = "Tab 1",
uiOutput("ui"),
rHandsontableOutput("hot")
),
bs4TabPanel(
tabName = "Tab 2",
p("Hey")
)
)
)
)
)
),
server = function(input, output) {
output$hot <- renderRHandsontable({ rhandsontable(mtcars[1:10, 1:3]) })
output$ui <- renderUI({
numericInput("num_ui", label = "Num In", value = 15)
})
}
)
Reproducible code for Picture 3 and Picture 4
library(shiny)
library(bs4Dash)
library(rhandsontable)
# Tabcard module ----------------------------------------------------------
mod_tabcard_ui <- function(id){
ns <- NS(id)
bs4TabCard(
id = ns("tabcard"), title = "Tab Card", side = "right",
bs4TabPanel(
tabName = "Tab 1",
uiOutput(ns("ui")),
rHandsontableOutput(ns("hot"))
),
bs4TabPanel(
tabName = "Tab 2",
mod_numinput_ui(ns("num"))
)
)
}
mod_tabcard_server <- function(input, output, session){
output$hot <- renderRHandsontable({ rhandsontable(mtcars[1:10, 1:3]) })
output$ui <- renderUI({
numericInput(session$ns("num_ui"), label = "Num In", value = 15)
})
callModule(mod_numinput_server, "num")
}
# Numeric input module ----------------------------------------------------
mod_numinput_ui <- function(id){
ns <- NS(id)
numericInput(ns("num"), "Num In", 0, 0, 10)
}
mod_numinput_server <- function(input, output, server){
return(reactive({input$num}))
}
# Section module ----------------------------------------------------------
mod_section_ui <- function(id){
ns <- NS(id)
mod_tabcard_ui(id = "tabcard")
}
mod_section_server <- function(input, output, session){
callModule(mod_tabcard_server, id = "tabcard")
}
# The app -----------------------------------------------------------------
shiny::shinyApp(
ui = bs4DashPage(
old_school = FALSE,
sidebar_min = TRUE,
sidebar_collapsed = FALSE,
controlbar_collapsed = FALSE,
controlbar_overlay = TRUE,
title = "Basic Dashboard",
navbar = bs4DashNavbar(),
sidebar = bs4DashSidebar(
sidebarMenu(
bs4Dash::menuItem(
text = "Introduction",
tabName = "tab-introduction",
icon = ""
)
)
),
controlbar = bs4DashControlbar(),
footer = bs4DashFooter(),
body = bs4DashBody(
bs4TabItems(
bs4TabItem(
tabName = "tab-introduction",
mod_section_ui(id = "mod")
)
)
)
),
server = function(input, output) {
callModule(mod_section_server, id = "mod")
}
)
you are missing a namespace in the mod_section_ui module. It should be:
mod_section_ui <- function(id){
ns <- NS(id)
mod_tabcard_ui(id = ns("tabcard"))
}