In my application, I have one module nested in another. Both the parent and child modules create a UI output using renderUI (a slider) and, based off of the value of this slider, filters data that is displayed on a ggplot. I'm familiar with this pattern in a regular ui/server situation - however, I'm not sure how to access the value of the slider when it's in a module.
The code below shows my attempt to do this for both a module that is called by UI, and by a nested module.
library(shiny)
library(dplyr)
library(ggplot2)
ui <- fluidPage(
  fluidRow(
    outerModUI("outer")
  )
)
outerModUI <- function(id) {
  ns <- NS(id)
  fluidPage(fluidRow(
    uiOutput(ns("outer_slider")),
    plotOutput(ns("outer_plot")),
    innerModUI(ns("inner"))
  ))
}
innerModUI <- function(id) {
  ns <- NS(id)
  fluidPage(fluidRow(
    uiOutput(ns("inner_slider")),
    plotOutput(ns("inner_plot"))
  ))
}
server <- function(input, output, session) {
  callModule(outerMod, "outer")
  output$outer_slider <- renderUI({
    sliderInput("slider1", label = "outer slider", min = round(min(mtcars$mpg)), 
      max = round(max(mtcars$mpg)), value = c(min(mtcars$mpg), max(mtcars$mpg), step = 1))
  })
  output$outer_plot <- renderPlot({
    data <- filter(mtcars, between(mpg, input$slider1[1], input$slider1[2]))
    ggplot(data, aes(mpg, wt)) + geom_point()
  })
}
outerMod <- function(input, output, session) {
  callModule(innerMod, "inner")
}
innerMod <- function(input, output, session) {
  output$inner_slider <- renderUI({
    sliderInput("slider2", label = "inner slider", min = round(min(mtcars$mpg)), 
      max = round(max(mtcars$mpg)), value = c(min(mtcars$mpg), max(mtcars$mpg), step = 1))
  })
  output$inner_plot <- renderPlot({
    data <- filter(mtcars, between(mpg, input$slider2[1], input$slider2[2]))
    ggplot(data, aes(mpg, wt)) + geom_point()
  })
}
shinyApp(ui = ui, server = server)
                Joe Cheng provided the answer on the shiny discuss mailing list.
1) In output$inner_slider's renderUI, change sliderInput("slider2", ...) to sliderInput(session$ns("slider2"), ...). This is how you get ahold of the namespace of the current module instance (innerMod).
2) I'd also add this to the first line of output$inner_plot: req(input$slider2)
This indicates that the render of that plot should not continue unless a value for input$slider2 exists (which it won't as the app starts up).
A working gist is here, with renderUI working correctly in both the parent and child modules. https://gist.github.com/tbadams45/38f1f56e0f2d7ced3507ef11b0a2fdce
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With