r - 使 Shiny 的应用程序模块彼此共享 react 值

标签 r shiny module

我正在尝试模块化一个 Shiny 的应用程序。到目前为止,一切进展顺利,但我在设计一个具有两个模块 A 和 B 的系统时遇到了麻烦,其中 A 需要来自 B 的数据,B 需要来自 A 的数据。

首先,请关注 this tutorial ( Shiny 版本 1.5)我让这个非常基本的独立示例可以工作。

library(shiny)

#######################
#     FILE MODULE     #
# Load and save value #
#######################
fileModuleUI <- function(id) {
  ns <- NS(id)

  tagList(
    fileInput(ns("fileInput"), "Input"),
    downloadButton(ns("fileOutput"), "Save problem")
  )
}

fileModuleServer <- function(id, textFieldData) {
  moduleServer(
    id,
    function(input, output, session) {

      # Write observer
      output$fileOutput <- downloadHandler(
        filename = function() { "myfile.dcf" },
        content = function(file) { dput(textFieldData(), file) }
      )

      # Read observers
      userFile <- reactive({
        validate(need(input$fileInput, message = FALSE))
        input$fileInput
      })

      fileContent <- reactive({
        dget(userFile()$datapath)
      })

      return(fileContent)
    }
  )
}

###############
#   MAIN UI   #
###############
ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(fileModuleUI("dataHandler")),
    mainPanel(textInput("mainData", label = "Type your data in here"))
  )
)

server <- function(input, output, session) {
  fileContent <- fileModuleServer("dataHandler", reactive(input$mainData))

  observe({
    updateTextInput(session, "mainData", value = fileContent())
  })
}

shinyApp(ui = ui, server = server)

Screenshot of Shiny app, on the left a load and save file button, on the right a textInput saying Hi There. Below the Shiny app it shows a save dialog

使用这个漂亮的工具,我可以从文件中的 textInput 加载并保存一行文本。

现在我还想模块化 mainPanel 中的内容。我们将其称为 mainModule

虽然构建 mainModuleUI 非常简单,但 mainModuleServer 引入了一些交叉依赖问题:

  • fileModuleServer 需要知道 mainModuleServer 的文本字段,以便将其值保存在文件中
  • mainModuleServer 需要从 fileModuleServer 了解文件内容,以便在加载文件时更新其文本输入字段

因此,服务器可能看起来有点像这样:

fileModuleServer <- function(id, textFieldData) { ... }
mainModuleServer <- function(id, fileContent) { ... }

server <- function(input, output, session) {
  # what to pass as second parameter?
  fileContent <- fileModuleServer("dataHandler", ???)

  # would passing fileContent even work?
  mainModuleServer("mainPanel", fileContent)
}

有什么好的方法可以解决这个问题吗?

最佳答案

我通过在我的主应用程序中引入 reactiveValue 来让它工作。然后我将该值传递给我的服务器,并通过写入 value('this is some new value') 更改其值,或通过调用 value() 读取其值。

这可能看起来像这样:

# Module A
moduleAServer <- function(id, someData) {
  moduleServer(
    id,
    function(input, output, session) {
      # when clicking on load-button, just pretend to load some data
      observeEvent(input$load, {
        someData('This is the new data!')
      })

      observeEvent(input$save, {
        print(paste('Saving the following:', someData()))
      })
    }
  )
}

# Module B
moduleBServer <- function(id, someData) {
  moduleServer(
    id,
    function(input, output, session) {
      # observe will be called when Module A changes the data inside someData
      observe({
        # not sure if I need this req
        req(someData)
        print(paste('some Data changed to', someData()))
      })
    }
  )
}

mainServer <- function(input, output, session) {
  someData <- reactiveVal('oh')
  chosenFile <- moduleAServer('filePanel', someData)
  inputServer <- moduleBServer('mainPanel', someData)
}

关于r - 使 Shiny 的应用程序模块彼此共享 react 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65727477/

相关文章:

r - 非等连接返回不存在的列名

r - dmvnorm MVN 密度 - RcppArmadillo 实现比 R 包慢,包括一些 Fortran

r - CentOS 安装 R 包 RLumShiny 失败

Python:完整的模块列表

ruby - Rails 按条件包含模块

r - 如何在 R 中使用 ggplot2 绘制类似的图?

r - 广义相加模型data.frame.default错误: attempting to apply nonfunction

shiny - R Shiny radioButtons 如何改变一些选择的颜色?

javascript - 如何在 Shiny 中创建一个弹出窗口来警告用户选择一种类型的文件扩展名?

module - 在 typescript 中封装子命名空间