Hello,
In some complex and large shiny apps, the UI parts are often rendered with renderUI
and uiOutput
. Consider this small one for illustration:
modUI <- function(id) {
ns <- NS(id)
uiOutput(ns("theUI"))
}
modServer <- function(id) {
moduleServer(
id,
function(input, output, session) {
output[["plot"]] <- renderPlot({
n <- input[["numb"]]
plot(rnorm(n), rnorm(n), pch = 19L)
})
ns <- session$ns
output[["theUI"]] <- renderUI({
tagList(
sliderInput(ns("numb"), "N", 10, 100, 50),
plotOutput(ns("plot"))
)
})
}
)
}
ui <- basicPage(
br(),
modUI("myapp")
)
server <- function(input, output, session) {
modServer("myapp")
}
Here modUI
is ridiculously small. But in modServer
, the renderUI
could be large and there could be many other output
components. Therefore it is desirable to split modServer
:
renderPlotServer <- function(id) {
moduleServer(
id,
function(input, output, session) {
output[["plot"]] <- renderPlot({
n <- input[["numb"]]
plot(rnorm(n), rnorm(n), pch = 19L)
})
}
)
}
renderUIServer <- function(id) {
moduleServer(
id,
function(input, output, session) {
ns <- session$ns
output[["theUI"]] <- renderUI({
tagList(
sliderInput(ns("numb"), "N", 10, 100, 50),
plotOutput(ns("plot"))
)
})
}
)
}
and to put them together one can use the same id
:
modServer <- function(id) {
moduleServer(
id,
function(input, output, session) {
renderPlotServer("mysubapp")
renderUIServer("mysubapp")
}
)
}
but then we need a nested namespace in the UI part of the module:
modUI <- function(id) {
ns <- NS(NS(id)("mysubapp"))
uiOutput(ns("theUI"))
}
Do you agree or am I overcomplicating something? Is there a simpler way?
I prefer to wait for some reactions before sharing my other thoughts...