当输入改变时,去抖定时器不重启

时间:2018-02-02 02:45:08

标签: r shiny debounce

我正在尝试创建一个日期输入,自动将输入的值更新到所选月份的末尾。我遇到的问题是,当我运行第一段代码(下面)时,如果用户尝试通过键入日期手动更改日期,则无法进行,因为输入会立即更新到月末在用户完成输入之前。

library(shinydashboard)
library(lubridate)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    dateInput(
      inputId = "date", 
      label = "End of Month Date", 
      value = ceiling_date(x = Sys.Date() + 365, unit = "month") - 1, 
      startview = "year"
    )
  )
)

server <- function(input, output, session) {
  observe({
    if(is.Date(input$date) & length(input$date) > 0){
      if(input$date != ceiling_date(input$date, unit = "month") - 1) {
        updateDateInput(
          session, 
          inputId = "date",
          value = ceiling_date(x = input$date, unit = "month") - 1
        )
      }
    }
  })
}

shinyApp(ui, server)

所以,我尝试实现debounce(如下所示 - 仅更改服务器代码),以便在用户输入完成之前将输入延迟更新;但是,我遇到了一个问题。根据我的理解,计时器不会在每个按键上重置。相反,定时器的操作就像我使用油门功能一样,并在输入首次更改时启动,并且在输入更改时不会重置。

server <- function(input, output, session) {
  observe({
    dateinputdelay <- debounce(r = reactive(input$date), millis = 2000)
    if(is.Date(dateinputdelay()) & length(dateinputdelay()) > 0){
      if(dateinputdelay() != ceiling_date(dateinputdelay(), unit = "month") - 1) {
        updateDateInput(
          session, 
          inputId = "date",
          value = ceiling_date(x = input$date, unit = "month") - 1
        )
      }
    }
  })
}

1 个答案:

答案 0 :(得分:0)

编辑:我能得到的最好的是下面的代码,但因为“花哨的日期输入东西”有自己的内部更新机制,与闪亮的reactive概念分开,这个去抖动只解决了一个问题来源。

第一个技巧是debounce需要在代码块开始之前发生。也就是说,它“取消”依赖代码块的开始;一旦他们开始,它没有帮助。

第二个是知道observe块试图急切地运行他们的代码 (参见shiny docs并阅读“详细信息”),而reactive块是相对的 lazy - 他们只根据需要运行相关代码。这是可能会受到伤害的“急切”部分。

此外,您在observe块中使用副作用来更新输入字段,但您从不将值存储在其他位置。我建议在一个地方计算新值可能会更好(以功能方式,例如中运行的reactive块效果),然后再使用它。

server <- function(input, output, session) {
  dateinputdelay <- debounce(reactive(input$date), 2000)
  end_of_month <- reactive({
    # print("react!")
    x <- dateinputdelay()
    if (is.Date(x) & length(x) > 0) {
      if (x != ceiling_date(x, unit = "month") - 1) {
        x <- ceiling_date(x = input$date, unit = "month") - 1
      }
    }
    x
  })
  observe({
    # print("observe!")
    updateDateInput(
      session, 
      inputId = "date",
      value = end_of_month()
    )
  })
}

(我在那里保留了几个print语句,不是因为它们在这里有很多帮助,而是因为它们可以成为一个很好的工具,可以看到何时/如何频繁的反应性导致代码块运行。)

正如我所说,我怀疑这种行为表明dateInput内的某些内容,而不是后续的reactiveobserve内容。