防止 pickerInput 在每次选择某些内容时更新(R、Shiny)

Ber*_*end 5 javascript r shiny

我已经搜索了 stackoverflow 和整个网络,但我找不到这个看似简单的问题的好答案。

情况如下:

  • 我有一个闪亮的应用程序,与数据库连接
  • 我有多个用户输入(Pickerinputs),用户可以在其中选择多个参数
  • 用户输入都是相互依赖的

出现的问题如下:

  • 如果用户勾选多个汽车品牌(例如雷诺、标致和宝马),则链接到此选择的选择器输入(这些品牌的特定汽车型号)将更新三次。由于许多选择器输入相互链接,这会造成混乱的用户体验。

需要解决方案

  • 我认为解决方案很简单:pickerinput 只需要在输入关闭后发送选定的值即可;它不需要在用户每次选择后发送值(并触发更新)。来自AirdatePickerInputShinywidgets 的具有此特定功能(update_on=c('change', 'close')。我需要的是我的 pickerInput在“关闭”时更新。这样结果值仅发送回服务器一次。

示例:用户界面

ui <- fluidPage(
  
  # Title panel
  fluidRow(
    column(2,
           wellPanel(
           h3("Filters"),
           uiOutput("picker_a"),
           uiOutput("picker_b"),
           )
    ),
  )
)
Run Code Online (Sandbox Code Playgroud)

服务器

server <- function(input, output, session) {
  
  # Start values for each filter  
  all_values_for_a <- tbl(conn, "table") %>%
    distinct(a) %>%
    collect()
  
  all_values_for_b <- tbl(conn, "table") %>%
    distinct(b) %>%
    collect()
  
  output$picker_a <- renderUI({
    pickerInput(
      inputId = "picker_a",
      label = "a:", 
      choices = all_values_for_a,
      selected = all_values_for_a,
      multiple = TRUE,
      options = list("live-search" = TRUE, "actions-box" = TRUE))
  })
  
  output$picker_b <- renderUI({
    pickerInput(
      inputId = "picker_b",
      label = "b:", 
      choices = all_values_for_b,
      selected = all_values_for_b,
      multiple = TRUE,
      options = list("live-search" = TRUE, "actions-box" = TRUE))
  })
  
  #I want this code to be executed ONLY when
  #picker_a is closed, not everytime when the user
  #picks an item in picker_a
  observeEvent(
    input$picker_a,
    {
      all_values_for_b <- tbl(conn, "table") %>%
        filter(a %in% !!input$picker_a) %>%
        distinct(b) %>%
        collect()
      updatePickerInput(session, "picker_b", choices = all_values_for_b, selected = all_values_for_b)
    })
    )
  )
}
Run Code Online (Sandbox Code Playgroud)

jul*_*ux5 3

一旦用户选择了所有值,您就可以使用actionButton来延迟更新的执行。

或者使用debounce函数,请参阅另一篇文章

编辑

GitHub 上的shinyWidgets 开发者(Victor Perrier)update_on = c("change", "close")向该功能请求了该小部件。pickerInput

维克多的回答是:

pickerInput 没有类似的参数,但有一个特殊的输入可以知道菜单是否打开。所以你可以使用中间的reactiveValue来达到相同的结果。

他提供了以下代码:

library(shiny)
library(shinyWidgets)

ui <- fluidPage(
  fluidRow(
    column(
      width = 4,
      pickerInput(
        inputId = "ID",
        label = "Select:",
        choices = month.name,
        multiple = TRUE
      )
    ),
    column(
      width = 4,
      "Immediate:",
      verbatimTextOutput("value1"),
      "Updated after close:",
      verbatimTextOutput("value2")
    ),
    column(
      width = 4,
      "Is picker open ?",
      verbatimTextOutput("state")
    )
  )
)

server <- function(input, output) {
  
  output$value1 <- renderPrint(input$ID)
  output$value2 <- renderPrint(rv$ID_delayed)
  output$state <- renderPrint(input$ID_open)
  
  rv <- reactiveValues()
  observeEvent(input$ID_open, {
    if (!isTRUE(input$ID_open)) {
      rv$ID_delayed <- input$ID
    }
  })
}

shinyApp(ui, server)
Run Code Online (Sandbox Code Playgroud)

对于你的情况你可以尝试:

  observeEvent(
    input$picker_a_open,
    {
    if (!isTRUE(input$picker_a_open)) {
      all_values_for_b <- tbl(conn, "table") %>%
        filter(a %in% !!input$picker_a) %>%
        distinct(b) %>%
        collect()
      updatePickerInput(session, "picker_b", choices = all_values_for_b, selected = all_values_for_b)
}
    })
Run Code Online (Sandbox Code Playgroud)