如何解决如何在 golem Shiny 应用程序中包含 R6 对象以跨模块共享数据
我第一次尝试使用 Shiny
创建一个 golem
应用。 golem
使用模块构建 Shiny
应用程序,以帮助保持大型 Shiny
应用程序模块化。但是,默认情况下,模块不相互通信。我想跨模块共享数据。根据 golem
文档,R6
objects are a useful way to share data across modules.
然而,在 example provided in the golem
documentation 中,不清楚将 R6
生成器放在哪里。根据 Appsilon,R6
生成器进入一个单独的 .R
文件(例如 logger_manager.R
),并在 global.R
中调用以构造一个新对象来自课堂:logger_manager = LoggerManager$new()
。但是,基于 global.R
的 golem
应用程序中没有 Shiny
文件。
以下是我的基于 golem
的 Shiny
应用的最小示例。我尝试遵循 example provided in the golem
documentation 中的结构,但它似乎没有跨模块共享数据:
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,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,questionnaire_responses){
ns <- session$ns
}
但是,不能跨模块共享数据,因为当我尝试在模块 B(在模块 A 中生成)中打印 resp_id
时,收到以下错误:
An error has occurred!
object 'questionnaire_responses' not found
解决方法
我对你的代码做了一些更正(一些错字)
tl;dr:您无法访问 UI 中的问卷调查回复。
app_ui.R
:
same as you
app_server.R
:
#' @import shiny
#' @import R6
#' @noRd
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.R
:
mod_a_ui <- function(id){
ns <- NS(id)
tagList(
radioButtons(inputId = ns("gender"),label = "What is your sex?",choices = c("Male" = 1,"Female" = 2),selected = character(0))
)
}
mod_a_server <- function(input,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_ui <- function(id){
ns <- NS(id)
tagList(
print("questionnaire_responses$resp_id") # you can't access questionnaire_responses in the UI
)
}
mod_b_server <- function(input,questionnaire_responses){
ns <- session$ns
print(questionnaire_responses$resp_id) # but here you can
}
,
所以这里的问题是,当您的 R6 对象被传递给服务器函数时,您正在尝试从 UI 函数打印对象。
换句话说,当 R6 对象传递给 mod_b_ui
函数时,您正在尝试在 mod_b_server
函数中进行打印。
对于您的原始问题,您可以在标准文件中创建 R6 类,如 https://github.com/ColinFay/golemexamples/blob/master/golemR6/R/R6.R
请注意,您的数据对象非反应性,并且在模块 A 中更改时不会重新打印 — 例如,您可以在此处使用 {gargoyle}
:
- init https://github.com/ColinFay/golemexamples/blob/master/golemR6/R/app_server.R#L12
- 触发https://github.com/ColinFay/golemexamples/blob/master/golemR6/R/mod_a.R#L43
- 观看https://github.com/ColinFay/golemexamples/blob/master/golemR6/R/mod_b.R#L22
有关完整的工作示例,请参阅 https://github.com/ColinFay/golemexamples/tree/master/golemR6。
PS:您的模块中缺少 ns() :)
科林
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。