【问题标题】:Hide boxes if input not suitable in Shiny如果在 Shiny 中输入不适合,则隐藏框
【发布时间】:2018-12-11 12:16:51
【问题描述】:

我正在使用闪亮和闪亮的仪表板。在某些情况下,我希望隐藏所有或大多数框/图。

  1. 如果日期范围不可能(即结束日期早于开始日期)。
  2. 如果选择的输入会使样本量过小。

对于问题 1,我想隐藏所有框并返回错误消息。对于问题 2,我想在顶部显示一些信息框(例如样本大小),但隐藏所有其余的框。

目前,我在第一个条件下使用 validate 生成错误消息,并在发生这种情况时使用 validate 来阻止绘图运行。然而,这仍然留下了盒子,即使它们是空的,这非常丑陋和凌乱。

我想我可能可以将每个框放入一个条件面板中,但这似乎非常重复 - 肯定有一种更简单的方法可以将参数传递给所有(或一组)框?此代码是一个示例 - 我正在开发的应用程序中有更多的框。

示例代码:

library(shiny)
library(shinydashboard)
library(tidyverse)


random_data <- data.frame(replicate(2, sample(0:10, 1000, rep=TRUE)))
set.seed(1984)
random_data$date <- sample(seq(as.Date('2016-01-01'), as.Date(Sys.Date()), by = "day"), 1000)

sidebar <- dashboardSidebar(dateRangeInput(
  "dates", label = h4("Date range"), start = '2016-01-01', end = Sys.Date(),
  format = "dd-mm-yyyy", startview = "year", min = "2016-01-01", max = Sys.Date()
))

body <- dashboardBody(
  textOutput("selected_dates"),
  br(),
  fluidRow(
        infoBoxOutput("total", width = 12)
  ),
  fluidRow(
    box(width = 12, solidHeader = TRUE,
        title = "X1 over time",
        plotOutput(outputId = "x1_time")
    )
  ),
  fluidRow(
    box(width = 12, solidHeader = TRUE,
        title = "X2 over time",
        plotOutput(outputId = "x2_time")
    )
  )
)

ui <- dashboardPage(dashboardHeader(title = "Example"),
                    sidebar,
                    body
)

server <- function(input, output) {
  filtered <- reactive({
    filtered_data <- random_data %>%
        filter(date >= input$dates[1] & date <= input$dates[2])
    return(filtered_data)
  })

  output$selected_dates <- renderText({
    validate(
      need(input$dates[2] >= input$dates[1], "End date is earlier than start date"
      )
    )
  })


  output$total<- renderInfoBox({
    validate(
      need(input$dates[2] >= input$dates[1], "")
    )
    infoBox(title = "Sample size", 
            value = nrow(filtered()), 
            icon = icon("binoculars"), color = "light-blue")
  })

  output$x1_time <- renderPlot({
    validate(
      need(input$dates[2] >= input$dates[1], "")
    )
    x1_time_plot <- ggplot(filtered(), aes(x = date, y = X1)) + 
      geom_bar(stat = "identity") 
      theme_minimal()
    x1_time_plot
  }) 

  output$x2_time <- renderPlot({
    validate(
      need(input$dates[2] >= input$dates[1], "")
    )
    x2_time_plot <- ggplot(filtered(), aes(x = date, y = X2)) + 
      geom_bar(stat = "identity") 
    theme_minimal()
    x2_time_plot
  }) 

}

shinyApp(ui, server)

【问题讨论】:

    标签: r shiny shinydashboard


    【解决方案1】:

    您可以在要隐藏或显示的所有 inputId 上使用 shinyjs 和 show/hide 方法,或者您可以将所有框放在带有类的 div 中,然后使用隐藏/显示这个类或直接分配一个类给fluidRows。 这两个示例都不再需要 validate+need。

    此示例显示/隐藏各个输出 ID:

    library(shiny)
    library(shinydashboard)
    library(tidyverse)
    library(shinyjs)
    
    ## DATA ##################
    random_data <- data.frame(replicate(2, sample(0:10, 1000, rep=TRUE)))
    set.seed(1984)
    random_data$date <- sample(seq(as.Date('2016-01-01'), as.Date(Sys.Date()), by = "day"), 1000)
    
    sidebar <- dashboardSidebar(dateRangeInput(
      "dates", label = h4("Date range"), start = '2016-01-01', end = Sys.Date(),
      format = "dd-mm-yyyy", startview = "year", min = "2016-01-01", max = Sys.Date()
    ))
    ##################
    
    ## UI ##################
    body <- dashboardBody(
      useShinyjs(),
      textOutput("selected_dates"),
      br(),
      fluidRow(
        infoBoxOutput("total", width = 12)
      ),
      fluidRow(
        box(width = 12, solidHeader = TRUE,
            title = "X1 over time",
            plotOutput(outputId = "x1_time")
        )
      ),
      fluidRow(
        box(width = 12, solidHeader = TRUE,
            title = "X2 over time",
            plotOutput(outputId = "x2_time")
        )
      )
    )
    
    ui <- dashboardPage(dashboardHeader(title = "Example"),
                        sidebar,
                        body
    )
    ##################
    
    
    server <- function(input, output) {
      filtered <- reactive({
        filtered_data <- random_data %>%
          filter(date >= input$dates[1] & date <= input$dates[2])
        return(filtered_data)
      })
    
      observe({
        if (input$dates[2] < input$dates[1]) {
          shinyjs::hide("total")
          shinyjs::hide("x1_time")
          shinyjs::hide("x2_time")
        } else {
          shinyjs::show("total")
          shinyjs::show("x1_time")
          shinyjs::show("x2_time")
        }
      })
    
      output$total<- renderInfoBox({
        infoBox(title = "Sample size", 
                value = nrow(filtered()), 
                icon = icon("binoculars"), color = "light-blue")
      })
    
      output$x1_time <- renderPlot({
        x1_time_plot <- ggplot(filtered(), aes(x = date, y = X1)) + 
          geom_bar(stat = "identity") 
        theme_minimal()
        x1_time_plot
      }) 
    
      output$x2_time <- renderPlot({
        x2_time_plot <- ggplot(filtered(), aes(x = date, y = X2)) + 
          geom_bar(stat = "identity") 
        theme_minimal()
        x2_time_plot
      }) 
    
    }
    
    shinyApp(ui, server)
    

    这个例子使用了fluidRows的类,所以这将隐藏仪表板的整个主页:

    ## UI ##################
    body <- dashboardBody(
      useShinyjs(),
      textOutput("selected_dates"),
      br(),
      fluidRow(class ="rowhide",
        infoBoxOutput("total", width = 12)
      ),
      fluidRow(class ="rowhide",
        box(width = 12, solidHeader = TRUE,
            title = "X1 over time",
            plotOutput(outputId = "x1_time")
        )
      ),
      fluidRow(class ="rowhide",
        box(width = 12, solidHeader = TRUE,
            title = "X2 over time",
            plotOutput(outputId = "x2_time")
        )
      )
    )
    
    ui <- dashboardPage(dashboardHeader(title = "Example"),
                        sidebar,
                        body
    )
    ##################
    
    
    server <- function(input, output) {
      filtered <- reactive({
        filtered_data <- random_data %>%
          filter(date >= input$dates[1] & date <= input$dates[2])
        return(filtered_data)
      })
    
      observe({
        if (input$dates[2] < input$dates[1]) {
          shinyjs::hide(selector = ".rowhide")
        } else {
          shinyjs::show(selector = ".rowhide")
        }
      })
    
      output$total<- renderInfoBox({
        infoBox(title = "Sample size", 
                value = nrow(filtered()), 
                icon = icon("binoculars"), color = "light-blue")
      })
    
      output$x1_time <- renderPlot({
        x1_time_plot <- ggplot(filtered(), aes(x = date, y = X1)) + 
          geom_bar(stat = "identity") 
        theme_minimal()
        x1_time_plot
      }) 
    
      output$x2_time <- renderPlot({
        x2_time_plot <- ggplot(filtered(), aes(x = date, y = X2)) + 
          geom_bar(stat = "identity") 
        theme_minimal()
        x2_time_plot
      }) 
    
    }
    
    shinyApp(ui, server)
    

    【讨论】:

    • 谢谢!我正在使用您的第二个示例,以便隐藏页面。我将在我概述的第二个实例中探索你的第一个实例。
    • 对于任何感兴趣的人,我最终使用了第二个版本(因为它避免了空框使页面混乱的问题),但定义了两个单独的类和两个单独的观察事件。所以一个隐藏一切,一个只是隐藏情节而不是信息框。一个示例 fluidRow 如下所示:fluidRow(class = "rowhide", class = "samplehide", box(width = 12, solidHeader = TRUE, title = "X1 over time", plotOutput(outputId = "x1_time") )
    猜你喜欢
    • 1970-01-01
    • 2016-07-29
    • 2017-06-27
    • 2021-02-27
    • 1970-01-01
    • 2023-03-29
    • 2011-09-11
    • 2017-01-08
    • 1970-01-01
    相关资源
    最近更新 更多