Calling shiny module based on reactive input

shiny-modules

#1

I would like to call a nested module server based on a reactive input and display the return output on the main panel. The function callModule doesn't seem to work here when it is depending on a reactive input.

I assume this to be a common scenario when you’re building a complex app but I’ve been struggling to find a solution.

Below is my code or you can run the app by entering the following command in R:
shiny::runGist("23abbb50a1df6a91af990a7401919044")

Thank you in advance.

csvFile_Input <- function(id, label = ".csv file") {

  ns <- NS(id)
  tagList(
    fileInput(ns("file"), label),
    checkboxInput(ns("heading"), "Has heading")
  )
}


# server
csvFile <- function(input, output, session){


  userFile <- reactive({
    req(input$file)
  })

  dataframe <- reactive({

    read.csv(userFile()$datapath,
             header = input$heading)
  })

  observe({
    msg <- sprintf("File %s was uploaded", userFile()$name)
    cat(msg, "\n")
  })



  return(dataframe)

}

othersource_Input <- function(id) {
  ns <- NS(id)
  textInput("text", label = h3("From the web"), value = "http://www.stats.ox.ac.uk/pub/datasets/csb/ch11b.dat")
}

othersource <- function(input, output, session){
  library(data.table)

  dataframe <- reactive({
    req(input$text)
    fread(input$text)
  })

   return(dataframe)
}

loadDataInput <- function(id){
  ns <- NS(id)
  wellPanel(
    tagList(
      uiOutput(ns("selectSource")),
      uiOutput(ns("text"))
    )
  )


}



loadData <- function(input, output, session){

  ns <- session$ns

  output$selectSource<-renderUI(
    radioButtons(
      ns("dt"), "Data source",
      c(csvFile = "fromCSV", web = "fromWeb"),
      inline = TRUE
    )
  )

  dtype <- reactive({
    req(input$dt)
  })


  output$text <- renderUI({
    req(dtype())
    if(dtype() == "fromCSV"){
      csvFile_Input(ns("user"))
    } else if (dtype() == "fromWeb"){
      othersource_Input(ns("web"))
    }
  })

# this is where the problem is
 data <- reactive({
    req(dtype())
    if(dtype() == "fromCSV"){
      callModule(csvFile, "user")
    } else if (dtype() == "fromWeb"){
      callModule(othersource, "web")
    }
  })


  output$viewinput <- renderPrint({
    print(data())
  })


  return(data)

}

loadDataOutput <- function(id){
  ns <- NS(id)
  verbatimTextOutput(ns("viewinput"))
}


ui <- fluidPage(
  titlePanel(paste("Calling module based on reactive input")),
  sidebarLayout(
    sidebarPanel(
      loadDataInput("test")
    ),
    mainPanel(
      loadDataOutput("test")
    )
  )
)

server <- function(input, output) {
  data <- callModule(loadData, "test")
}

shiny::shinyApp(ui = ui, server = server)


#2

Hi @tellyshia,

perhaps this article https://itsalocke.com/blog/shiny-module-design-patterns-pass-module-inputs-to-other-modules/ may help you. It explains how to set up a connection of modules and to pass inputs from one to another module.

Best regards
Sebastian