Reputation: 11
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.
library(shiny)
# innerModule 1
csvFile_Input <- function(id, label = ".csv file") {
# Create a namespace function using the provided id
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)
}
# innerModule 2
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
# Select source from user or from wibi
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"))
}
})
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) {
callModule(loadData, "test")
}
shiny::shinyApp(ui = ui, server = server)
Upvotes: 1
Views: 1049
Reputation: 7695
You shouldn't invoke callModule
inside renderXXX
or reactive
functions. The following changes worked for me.
csvinput <- callModule(csvFile, "user")
otherinput <- callModule(othersource, "web")
data <- reactive({
req(dtype())
if(dtype() == "fromCSV"){
csvinput()
} else if (dtype() == "fromWeb"){
otherinput()
}
})
Also, you should use ns("text")
in othersource_Input
. If you want further explanations, please provide a minimal example.
Upvotes: 2