1

我想构建一个具有“输入模块”的应用程序,该模块将根据用户输入准备数据。一个简单的例子是让用户输入要保存在 mtcars 中的最小和最大 MPG。在这种情况下,“输入模块”将返回三个值:过滤后的 mtcars 数据集、最小 MPG 和最大 MPG。

多个输出模块将使用输入模块的输出。假设第一个模块生成 table1,它只是过滤数据的 DT::datatable。我们还想在表格标题中打印最小和最大 MPG。

这是我设法开始工作的内容:
a)输入模块具有“提交”按钮,但在此处返回单个值(过滤后的 mtcars 数据) 代码
b)输入模块没有“提交”按钮并返回值列表(过滤后的 mtcars 数据,最小 mpg 和最大 mpg)。 代码在这里

我没有设法开始工作的是:
c)输入模块有一个“提交”按钮并返回一个值列表。代码在这里

该代码出现以下错误:

Listening on http://127.0.0.1:4493
Warning: Error in $: object of type 'closure' is not subsettable
52: is.reactive
50: mod_table1Output_server [#2]
49: server [#16]
Error in data$df : object of type 'closure' is not subsettable

我认为当 Table1Output 模块尝试获取 data$df 并且我还没有单击“提交”按钮时,它是 NULL。不知道如何解决这个问题。

编辑:这些看起来很有趣: 在 R Shiny 中跨多个模块使用 reactiveValues

https://github.com/ardata-fr/Shiny-Modules-Tutorials

4

1 回答 1

0

已解决:一旦列表依赖于 eventReactive,其内容不再需要是响应式的。

library(shiny)
library(shinyWidgets)
library(dplyr)
mod_filterDataInputMPG_ui <- function(id){
  ns <- NS(id)
  shinyWidgets::numericRangeInput(
    inputId = ns("mpg_range"), 
    label = "mpg_range",
    value = c(0, 99)
  )
}

mod_filterDataInputGo_ui <- function(id){
  ns <- NS(id)
  actionButton(
    inputId = ns("go"), 
    label = "Go")
}

mod_filterDataInput_server <- function(id,df){
  stopifnot(!is.reactive(df)) # df shouldnt be reactive here .. it is mtcars
  moduleServer( id, function(input, output, session){
    ns <- session$ns
    eventReactive(input$go,{
      list(
        df = #reactive( 
          df %>%
            dplyr::filter(
              mpg >= input$mpg_range[1] &
                mpg <= input$mpg_range[2]
            ),
        mpg_min = input$mpg_range[1],
        mpg_max = input$mpg_range[2]
      )
    })
  })
}

mod_table1Output_ui <- function(id){
  ns <- NS(id)
  tagList(
    DT::dataTableOutput(ns("table1"))
  )
}

mod_table1Output_server <- function(id,d){#f, mpg_min, mpg_max){
  # stopifnot(is.reactive(df)) # df here should be reactive.. it is mtcars after being filtered by the user-selectable inputs
  # stopifnot(is.reactive(mpg_min))
  # stopifnot(is.reactive(mpg_max))
  moduleServer( id, function(input, output, session){
    ns <- session$ns
    
    output$table1 <- DT::renderDataTable({
      data <- d()
      df <- data$df
      mpg_min <- data$mpg_min
      mpg_max <- data$mpg_max
      df %>% 
        select(mpg, cyl, disp) %>% 
        DT::datatable(
          caption = paste0("list of cars with mpg between ", mpg_min, " and ", mpg_max),
          rownames = FALSE,
          escape = FALSE
        )
    })
  })
}



myApp <- function() {
  ui <- fluidPage(
    sidebarLayout(
      sidebarPanel(
        mod_filterDataInputMPG_ui("filterDataInput_ui_1"),
        mod_filterDataInputGo_ui("filterDataInput_ui_1")
      ),
      mainPanel(
        mod_table1Output_ui("table1Output_ui_1")
      )
    )
  )
  
  server <- function(input, output, session) {
    data <- mod_filterDataInput_server("filterDataInput_ui_1", mtcars)
    mod_table1Output_server("table1Output_ui_1", data)#df= data$df, mpg_min =data$mpg_min, mpg_max = data$mpg_max)
  }
  shinyApp(ui, server)
} 
myApp()
于 2022-01-09T18:18:01.323 回答