R 在系统中使用模块

R 在系统中使用模块,r,shiny,R,Shiny,我正在尝试构建一个闪亮的仪表板,并且我希望合并闪亮的模块。在每个选项卡中,应用程序的UI都非常相似,有一个selectInput、dateRangeInput和同一数据集的一个操作按钮。因此,我认为如果我应用模块,代码会大大缩短。我的第一次尝试是使用actionbutton模块,如果我的方法正确,或者您有任何改进建议,我希望得到您的反馈 下面的迷你应用程序的想法是,只有当您单击相应的按钮(按钮1用于绘图1,按钮2用于绘图2)时,数据和绘图才会更新 这是一个小例子,但是考虑一个有20个不同标签的闪

我正在尝试构建一个闪亮的仪表板,并且我希望合并闪亮的模块。在每个选项卡中,应用程序的UI都非常相似,有一个selectInput、dateRangeInput和同一数据集的一个操作按钮。因此,我认为如果我应用模块,代码会大大缩短。我的第一次尝试是使用actionbutton模块,如果我的方法正确,或者您有任何改进建议,我希望得到您的反馈

下面的迷你应用程序的想法是,只有当您单击相应的按钮(按钮1用于绘图1,按钮2用于绘图2)时,数据和绘图才会更新

这是一个小例子,但是考虑一个有20个不同标签的闪亮的仪表板,我认为它会使代码更容易阅读,而不是每次只为每个选项卡写按钮UI。类似地,我希望为select_ui和daterange_ui提供类似的功能

ec <- data.frame(
       country = c("US", "UK", "Germany", "Spain", "India"), 
       A  = c("1", "2", "2", "3", "3"), 
       B = c(100, 200, 300, 400, 500)
   )

## MODULE 
library(shiny)
library(tidyverse)
library(ggplot2)

button_ui <- function(id) {
  actionButton(NS(id, "btn"), label = "Apply")
}

button_server <- function(id) {
  moduleServer(id, function(input, output, session) {
    reactive(input$btn)
  })
}

## BUILDING THE APP 

ui <- fluidPage(
  
  selectInput(
    "choice",
    "Select Country:",
    multiple = TRUE,
    choices = unique(ec$country),
    selected = "US"),
  
  button_ui("btn1"),
  button_ui("btn2"),
  plotOutput("plot1"),
  br(),
  plotOutput("plot2")
)

server <- function(input, output, session) {
  
  button <- button_server("btn1")
  button_a <- button_server("btn2")
  
  dt <- reactive({button()
    isolate(
    ec %>% filter(country %in% input$choice)
    )
  })
  
  dt1 <- reactive({button_a()
    isolate(
      ec %>% filter(country %in% input$choice)
    )
  })
  
  output$plot1 <- renderPlot({
    ggplot(dt(), aes(x = country, y = A)) + 
      geom_bar(stat = "identity") + 
      theme_test()
  })
  
  output$plot2 <- renderPlot({
    ggplot(dt1(), aes(x = country, y = B)) + 
      geom_bar(stat = "identity") + 
      theme_test()
  })
  

}

shinyApp(ui, server)

ec您对模块的一般使用是正确的,但我认为您的actionbutton模块太精细了。基本上,您只围绕一个UI元素包装一个模块,因此产生的开销大于有用性。但是,我认为在您的情况下,将
selectInput
和绘图输出组合在一个模块中是有意义的。您可以在下面的示例中看到这一点。我还改变了以下几点:

  • 我使用
    eventReactive
  • 我使用闪亮1.5.0中的新模块界面

这似乎更有意义。谢谢你的建议@starja。请允许我问一下,为什么在手头的案例中使用EventResponsive而不是Responsive和isolate?至少在我的案例中,它在第一次单击按钮之前已经显示了绘图。另外,
eventReactive
正是提供所需功能的函数:它生成一个被动输出,仅当第一个表达式(操作按钮)的值更改时才会更改。因此,您需要输入更少的代码,通过查看代码,您可以直接推断此反应式的行为(您不必查找
隔离
语句,在更复杂的代码中,这些语句可能更复杂)。感谢您的解释。这是有道理的
ec <- data.frame(
  country = c("US", "UK", "Germany", "Spain", "India"), 
  A  = c("1", "2", "2", "3", "3"), 
  B = c(100, 200, 300, 400, 500)
)

## MODULE 
library(shiny)
library(dplyr)
library(ggplot2)


tab_module_ui <- function(id) {
  ns <- NS(id)
  
  tabPanel(
    title = paste0("Plot ", id),
    selectInput(
      ns("choice"),
      "Select Country:",
      multiple = TRUE,
      choices = unique(ec$country),
      selected = "US"),
    actionButton(ns("btn"), label = "Apply"),
    plotOutput(ns("plot"))
    
  )
  
}

tab_module <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      dt <- eventReactive(input$btn, {
          ec %>% filter(country %in% input$choice)
      })
      
      output$plot <- renderPlot({
        ggplot(dt(), aes(x = country, y = A)) + 
          geom_bar(stat = "identity") + 
          theme_test()
      })
    }
  )
}

## BUILDING THE APP 

ui <- fluidPage(
  
  tabsetPanel(
    tab_module_ui("plot-1"),
    tab_module_ui("plot-2")
  )
)

server <- function(input, output, session) {
 
  tab_module("plot-1")
  tab_module("plot-2")
  
  
}

shinyApp(ui, server)