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

标签 r shiny module r6 golem

我正在尝试创建一个 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, 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
  }
但是,数据不能跨模块共享,因为当我尝试打印 resp_id 时在模块 B(在模块 A 中生成)中,我收到以下错误:
An error has occurred!
object 'questionnaire_responses' not found

最佳答案

所以这里的问题是您正在尝试打印对象 来自 UI 功能 当您的 R6 对象通过 到服务器函数 .
换句话说,您正试图在 mod_b_ui 中进行打印。函数,当 R6 对象被传递给 mod_b_server功能。
对于您的原始问题,您可以在标准文件中创建 R6 类,如 https://github.com/ColinFay/golemexamples/blob/master/golemR6/R/R6.R
请注意,您的数据对象是 无 react 并且当您在模块 A 中更改时不会重新打印 - 这是您可以使用 {gargoyle} 的地方例如:

  • 初始化 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
  • watch https://github.com/ColinFay/golemexamples/blob/master/golemR6/R/mod_b.R#L22

  • 请看 https://github.com/ColinFay/golemexamples/tree/master/golemR6一个完整的工作示例。
    PS:您的模块中缺少 ns() :)
    科林

    关于r - 如何在 golem Shiny 应用程序中包含 R6 对象以跨模块共享数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67075905/

    相关文章:

    arrays - R中的字符串数组组合

    python - 如何将我的 Python 文件分离到多个插件?

    android - 应用看不到模块的 Activity

    r - pmatch() 无法识别向量之间的部分字符串匹配

    r - 快速数据表过滤

    r - 由于 "undefined reference to ` libiconv'",安装 R 失败

    swift - 许多目标中的相同扩展

    html - ioslides 中 Shiny 的应用程序大小

    r - Shiny R - 下载表格的结果

    在 Shiny 中使用迷你图渲染数据表