Search code examples
shinyshinymodules

Call for input inside moduleServer


I'm learning Shiny modules. And I'm stuck in a very silly thing: I don't know how to call an input inside moduleServer. In this reprex, the table does not show, I think its because the getInput argument is not properly used in the server. Here's a reprex:

library(shiny)
library(DT)

tablaResumen <- function(id, getInput, tabla1, tabla2) {
  moduleServer(id, function(input, output, session) {
    output$table <- renderDT({
      if(getInput == FALSE){
        tabla <- tabla1
        }else{
        tabla <- tabla2
        }
      DT::datatable(tabla, escape = FALSE, rownames = FALSE)
    })  
  })
}

ui <- fluidPage(
  checkboxInput("input1", label = "Change table"),
  DTOutput("table1")
  )

server <- function(input, output, session) {
  tablaResumen("table1", input$input1, mtcars, iris)
}

shinyApp(ui, server)

Solution

  • 
    library(shiny)
    library(DT)
    
    tablaResumen <- function(id, parent_in, get, tabla1, tabla2) {
      moduleServer(id, function(input, output, session) {
        output$mytable <- renderDT({
           
          if(parent_in[[get]] == FALSE){
            tabla <- tabla1
          }else{
            tabla <- tabla2
          }
          DT::datatable(tabla, escape = FALSE, rownames = FALSE)
        })  
      })
    }
    
    tablaResumenUI <- function(id) {
      ns <- NS(id)
      DTOutput(ns("mytable"))
    }
    
    ui <- fluidPage(
      checkboxInput("input1", label = "Change table"),
      tablaResumenUI("table")
    )
    
    server <- function(input, output, session) {
      tablaResumen("table", parent_in = input, "input1", mtcars, iris)
    }
    
    shinyApp(ui, server)
    

    Things are a little tricky here.

    1. To render the table, you must put the DTOutput under the same namespace as your mod server. The way we usually do it is by creating a mod UI function and use NS to wrap the id to create the namespace.
    2. You module is depend on a reactive input value input$input1, but the server function itself is not reactive. This means if you provide it as an argument for the mod function, it will be run only one time, so getInput will never be changed after the app is initialized. It becomes a fixed value. To get the reactive value of input1, you need to provide the parent input as an argument as access from there.