如何包含 R6 对象以在 golem Shiny 应用程序中跨模块共享数据

itp*_*sen 7 module r shiny r6 golem

我\xe2\x80\x99m第一次尝试创建一个Shiny应用程序。使用模块构建应用程序,以帮助保持大型应用程序的模块化。但是,默认情况下,模块之间不\xe2\x80\x99 相互通信。I\xe2\x80\x99d 喜欢跨模块共享数据。根据文档,对象是跨模块共享数据的有用方法golemgolemShinyShinygolemR6

\n

然而,在文档中提供的示例golem中,并不清楚将R6生成器放在哪里。根据Appsilon 的说法,R6生成器进入一个单独的.R文件(例如logger_manager.R),并进行调用global.R以从类构造一个新对象:logger_manager = LoggerManager$new()。但是,基于 的应用程序中没有global.R文件。golemShiny

\n

golem下面是我的应用程序的一个最小示例Shiny我尝试遵循文档中提供的示例golem中的结构,但它似乎没有跨模块共享数据:

\n

app_ui.R:

\n
app_ui <- function(request) {\n  tagList(\n    # Leave this function for adding external resources\n    golem_add_external_resources(),\n    \n    # List the first level UI elements here \n    fluidPage(\n      mod_a_ui("a_ui_1"),\n      mod_b_ui("b_ui_1")\n    )\n  )\n}\n\ngolem_add_external_resources <- function(){\n  \n  add_resource_path(\n    \'www\', app_sys(\'app/www\')\n  )\n \n  tags$head(\n    favicon(),\n    bundle_resources(\n      path = app_sys(\'app/www\'),\n      app_title = \'Test\'\n    ),\n    # Add here other external resources\n    # for example, you can add shinyalert::useShinyalert()\n    shinyjs::useShinyjs()\n  )\n}\n
Run Code Online (Sandbox Code Playgroud)\n

app_server.R:

\n
app_server <- function( input, output, session ) {\n  \n  # Generate R6 Class\n  QuestionnaireResponses <- R6Class(\n    classname = "QuestionnaireResponses",\n    public = list(\n      resp_id = NULL,\n      timezone = NULL,\n      timestamp = NULL,\n      gender = NULL,\n    )\n  )\n  \n  # Create new object to share data across modules using the R6 Class\n  questionnaire_responses <- QuestionnaireResponses$new()\n  \n  # List the first level callModules here\n  callModule(mod_a_server, "a_ui_1", questionnaire_responses)\n  callModule(mod_b_server, "b_ui_1", questionnaire_responses)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

mod_a.R:

\n
mod_a_ui <- function(id){\n  ns <- NS(id)\n  \n  tagList(\n    radioButtons(inputId = "gender",\n                 label = "What is your sex?",\n                 choices = c("Male" = 1,\n                             "Female" = 2),\n                 selected = character(0))\n)\n}\n\nmod_a_server <- function(input, output, session, questionnaire_responses){\n  ns <- session$ns\n  \n  # Add time start to the output vector\n  timestamp <- format(Sys.time(), "%Y-%m-%d %H:%M:%OS6")\n  timezone <- Sys.timezone()\n  \n  # Generate a survey-specific ID number\n  resp_id <- paste0(sample(c(letters, LETTERS, 0:9), 10), collapse = "")\n  \n  # Assign values to R6 object\n  questionnaire_responses$resp_id <- resp_id\n  questionnaire_responses$timezone <- timezone\n  questionnaire_responses$timestamp <- timestamp\n  questionnaire_responses$gender <- input.gender\n}\n
Run Code Online (Sandbox Code Playgroud)\n

mod_b.R:

\n
mod_b_ui <- function(id){\n  ns <- NS(id)\n  tagList(\n    print("questionnaire_responses$resp_id")\n  )\n}\n\nmod_b_server <- function(input, output, session, questionnaire_responses){\n  ns <- session$ns\n  }\n
Run Code Online (Sandbox Code Playgroud)\n

但是,数据不得跨模块共享,因为当我尝试resp_id在模块 B(在模块 A 中生成)中打印时,我收到以下错误:

\n
An error has occurred!\nobject \'questionnaire_responses\' not found\n
Run Code Online (Sandbox Code Playgroud)\n

Col*_*FAY 5

因此,这里的问题是,当 R6 对象传递到服务器函数时,您试图从 UI 函数打印对象。

\n

mod_b_ui换句话说,当 R6 对象传递给函数时,您尝试在函数中进行打印mod_b_server

\n

对于您原来的问题,您可以在标准文件中创建 R6 类,如https://github.com/ColinFay/golemexamples/blob/master/golemR6/R/R6.R

\n

请注意,尽管您的数据对象不是反应性的,并且当您在模块 A \xe2\x80\x94 中更改时不会重新打印,但您可以在此处使用,{gargoyle}例如:

\n\n

请参阅https://github.com/ColinFay/golemexamples/tree/master/golemR6了解完整的工作示例。

\n

PS:您的模块中缺少 ns() :)

\n

科林

\n