I'm working on an app with a dynamic number of modules which take module-specific reactive values. If the value is non-reactive, using force
(per #1711) fixes the problem but I just can't figure out how to get around reactive values due to lazy evaluation.
This is a simplified, reproducible version. The actual version is a Shiny-powered app for interfacing with any discrete Bayesian network, where every node is a module and can be unobserved (in which case the probabilities are inferred) or observed -- in which case it is evidence that propagates to other nodes (modules) -- so I'm trying to figure out how handle dynamically-named reactive values in a programmatic way.
The goal here is that every module renders the selected values from the other modules.
library(shiny)
modUI <- function(id) {
ns <- NS(id)
wellPanel(
h3(id),
selectInput(ns("choices"), "Choose:", choices = LETTERS[1:4], selected = "A"),
verbatimTextOutput(ns("others"))
)
}
mod <- function(input, output, session, label, rvar) {
force(label) # due to lazy evaluation
output$others <- renderPrint({
paste0("outside of ", label, ": ", paste0(rvar(), collapse = ", "))
})
return(input$choices)
}
launch_app <- function(N = 3) {
module_uis <- purrr::map(1:N, function(n) {
return(modUI(n))
})
ui <- fluidPage(
tagList(module_uis)
)
initial_rvars <- paste0(rep("A", N - 1), collapse = ", ")
server <- function(input, output, session) {
modules <- reactiveValues()
rvars <- reactiveValues()
for (n in as.character(1:N)) {
# populate the reactive vars with some initial values:
rvars[[n]] <- reactive({ initial_rvars })
}
observe({
for (n in as.character(1:N)) {
modules[[n]] <- callModule(mod, n, label = n, rvar = rvars[[n]])
}
})
observe({
for (n in as.character(1:N)) {
others <- setdiff(as.character(1:N), n)
rvals <- reactiveValuesToList(modules)[others]
rvals_subset <- rvals[others]
rval <- paste0(purrr::map_chr(rvals_subset, ~ .x()), collapse = ", ")
rvars[[n]] <- reactive({ rval })
}
})
}
shinyApp(ui, server)
}
launch_app()
This is what I get:
Warning: Error in .x: could not find function ".x"
51: .f
50: purrr::map_chr
48: <observer> [~/Desktop/reproducible.R#48]
5: runApp
3: print.shiny.appobj
1: source
and I'm stumped. What am I doing wrong or not seeing here? Or are Shiny modules just not built to handle this kind of logic?