I’m trying to create a Shiny app using golem for the first time. golem structures Shiny apps with modules to help keep large Shiny apps modularized. However, modules don’t communicate with each other by default. I’d like to share data across modules. According to the golem documentation, R6 objects are a useful way to share data across modules.
However, in the example provided in the golem documentation, it is unclear where to put the R6 generator. According to Appsilon, the R6 generator goes in a separate .R file (e.g., logger_manager.R), and places a call in global.R to construct a new object from the class: logger_manager = LoggerManager$new(). However, there is no global.R file in a golem-based Shiny app.
Below is a minimal example of my golem-based Shiny app. I tried to follow the structure in the example provided in the golem documentation, but it does not seem to be sharing data across modules:
app_ui.R:
app_ui <- function(request) {
tagList(
# Leave this function for adding external resources
golem_add_external_resources(),
# List the first level UI elements here
fluidPage(
mod_a_ui("a_ui_1"),
mod_b_ui("b_ui_1")
)
)
}
golem_add_external_resources <- function(){
add_resource_path(
'www', app_sys('app/www')
)
tags$head(
favicon(),
bundle_resources(
path = app_sys('app/www'),
app_title = 'Test'
),
# Add here other external resources
# for example, you can add shinyalert::useShinyalert()
shinyjs::useShinyjs()
)
}
app_server.R:
app_server <- function( input, output, session ) {
# Generate R6 Class
QuestionnaireResponses <- R6Class(
classname = "QuestionnaireResponses",
public = list(
resp_id = NULL,
timezone = NULL,
timestamp = NULL,
gender = NULL,
)
)
# Create new object to share data across modules using the R6 Class
questionnaire_responses <- QuestionnaireResponses$new()
# List the first level callModules here
callModule(mod_a_server, "a_ui_1", questionnaire_responses)
callModule(mod_b_server, "b_ui_1", questionnaire_responses)
}
mod_a.R:
mod_a_ui <- function(id){
ns <- NS(id)
tagList(
radioButtons(inputId = "gender",
label = "What is your sex?",
choices = c("Male" = 1,
"Female" = 2),
selected = character(0))
)
}
mod_a_server <- function(input, output, session, questionnaire_responses){
ns <- session$ns
# Add time start to the output vector
timestamp <- format(Sys.time(), "%Y-%m-%d %H:%M:%OS6")
timezone <- Sys.timezone()
# Generate a survey-specific ID number
resp_id <- paste0(sample(c(letters, LETTERS, 0:9), 10), collapse = "")
# Assign values to R6 object
questionnaire_responses$resp_id <- resp_id
questionnaire_responses$timezone <- timezone
questionnaire_responses$timestamp <- timestamp
questionnaire_responses$gender <- input.gender
}
mod_b.R:
mod_b_ui <- function(id){
ns <- NS(id)
tagList(
print("questionnaire_responses$resp_id")
)
}
mod_b_server <- function(input, output, session, questionnaire_responses){
ns <- session$ns
}
However, the data must not be being shared across modules because when I try to print resp_id in module B (which was generated in module A), I receive the following error:
An error has occurred!
object 'questionnaire_responses' not found