Home > Enterprise >  General input for different modules in shiny
General input for different modules in shiny

Time:11-22

I have a ui and a server module in shiny just like in an example in 'Mastering Shiny' by Hadley Wickham:

histogramUI <- 
  function(id){
    tagList(
    selectInput(NS(id, "var"), "Variable", choices = names(mtcars)),
    numericInput(NS(id, "bins"), "bins", value = 10, min = 1),
    plotOutput(NS(id, "hist"))
  )
}


histogramServer <- 
  function(id){
    moduleServer(id, function(input, output, session){
      data <- reactive(mtcars[[input$var]])
      output$hist <- renderPlot({
        hist(data(), breaks = input$bins, main = input$var)
      }, res = 96)
    })
  }

Now I want to create the app with two inputs and outputs named by "hist1" and "hist2".

That works fine with the following code:

histogrammApp <- 
  function(){
    ui <- fluidPage(
      histogramUI("hist1"),
      histogramUI("hist2")
    )
    server <- function(input, output, session){
      histogramServer("hist1")
      histogramServer("hist2")
    }
    shinyApp(ui, server)
  }

Each plot has its own input parameters.

Let's say I want to have a general input bins instead so that both plots will have the same amount of breaks in a numericInput. How could I achieve this?

My first attempt was to remove the line numericInput(NS(id, "bins"), "bins", value = 10, min = 1), and place the line tagList(numericInput("bins", "bins", value = 10, min = 1)), before the line histogramUI("hist1"), but this did not work. I get the following error: Invalid breakpoints produced by 'breaks(x)': NULL. input$bins is NULL, I guess. I think because it is in a different namespace? How could I come up with the problem?

CodePudding user response:

You should consider passing the input$bins as a reactive to histogramServer("hist1",reactive(input$bins)). Try this

histogramUI <-  function(id){
    tagList(
      selectInput(NS(id, "var"), "Variable", choices = names(mtcars)),
      #numericInput(NS(id, "bins"), "bins", value = 10, min = 1),
      plotOutput(NS(id, "hist"))
    )
  }


histogramServer <-  function(id,bins){
    moduleServer(id, function(input, output, session){
      data <- reactive(mtcars[[input$var]])
      output$hist <- renderPlot({
        hist(data(), breaks = bins(), main = input$var)
      }, res = 96)
    })
  }

#histogrammApp <- function(){
    ui <- fluidPage(
      numericInput("bins", "Bins", value = 10, min = 1),
      histogramUI("hist1"),
      histogramUI("hist2")
    )
    server <- function(input, output, session){
      histogramServer("hist1",reactive(input$bins))
      histogramServer("hist2",reactive(input$bins))
    }
    shinyApp(ui, server)
#   }
# 
# histogrammApp()
  • Related