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