Separate `renderUI` in a module server - nested namespaces

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...

A simpler way, to avoid the nested namespace, would be:

modServer <- function(id) {
  moduleServer(
    id, 
    function(input, output, session) {
      renderPlotServer(NULL)
      renderUIServer(NULL)
    }
  )
}

Is it a good practice?

I think the NULL namespace is not a good practice, because it prevents to use the module multiple times.

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.