1

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

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)

因此,我尝试实现去抖动(如下所示 - 仅更改服务器代码),以便延迟输入更新,直到用户完成输入;但是,我遇到了一个问题。正如我所理解的那样,计时器不会在每次击键时重置。相反,计时器就像我使用油门功能一样运行,并在输入第一次更改时启动,并且在输入更改时不会重置。

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
        )
      }
    }
  })
}
4

1 回答 1

1

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

第一个技巧是debounce需要在代码块开始之前发生。也就是说,它对依赖代码块的开始“去抖动”;一旦启动,它就无济于事。

第二个是知道observe块试图急切地运行它们的代码(参见闪亮的文档并阅读“详细信息”),而reactive块相对懒惰——它们只在需要时运行依赖的代码。可能会受到伤害的是“渴望”的部分。

此外,您在块中使用副作用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,而不是后续的reactiveorobserve块中的东西。

于 2018-02-02T03:28:29.113 回答