返回

R Shiny rhandsontable 中的条件表格重置:如何仅在特定条件下重置表格?

javascript

在 R Shiny rhandsontable 中实现条件表格重置

问题

在使用 R Shiny 应用程序时,用户更改 sliderInput()(对象 input$periods)会导致所有变量用户输入表格被重置,而理想情况下,我们只希望重置其中特定条件的表格。具体来说,我们希望仅当 input$periods 中的更改导致 X 列中最大值超过新重置值时,才重置该表格。

解决方法

要解决此问题,我们需要修改 rhandsontable 中的 beforeRemoveRow 挂钩。以下是修改后的挂钩代码:

function(el, x) {
  var hot = this.hot;
  Handsontable.hooks.add('beforeRemoveRow', function(index, amount){
    var nrows = hot.countRows();
    if(nrows === 1) {
      return false;
    }
    if(index === 0) {
      var maxVal = hot.getDataAtCell(index, hot.propToCol('X'));
      if(maxVal > input$periods) {
        return false;
      }
    }
  }, hot);
}

此修改执行以下操作:

  • 检查正在删除的行数是否为 1。如果是,则取消删除,因为 X/Y 表格中至少需要有一行。
  • 如果正在删除第一行,则检查“X”列中的最大值是否大于 input$periods 的新值。如果是,则取消删除该行。

更新的代码

将此修改后的挂钩代码与原始代码一起使用,可以实现条件重置,即仅在 “X”列的最大值超过 input$periods 的新值时才重置 X/Y 表格。以下是更新的代码:

library(shiny)
library(rhandsontable)
library(htmlwidgets)

jsCode <- c(
  "function(el, x) {",
  "  var hot = this.hot;",
  "  Handsontable.hooks.add('beforeRemoveRow', function(index, amount){",
  "    var nrows = hot.countRows();",
  "    if(nrows === 1) {",
  "      return false;",
  "    }",
  "    if(index === 0) {",
  "      var maxVal = hot.getDataAtCell(index, hot.propToCol('X'));",
  "      if(maxVal > input$periods) {",
  "        return false;",
  "      }",
  "    }",
  "  }, hot);",
  "}"
)

ui <- fluidPage(
  sliderInput("periods", "Time window (W):", min = 1, max = 10, value = 5),
  h5(strong("Variable (Y) over window (W):")),
  rHandsontableOutput("base_input"),  
  uiOutput("Vectors")
)

server <- function(input, output, session) {
  numVars <- 2  # Number of variables to model
  varValues <- lapply(1:numVars, function(i) { reactiveValues(data = 20) })
  lastGoodFirstRows <- lapply(1:numVars, function(i) { reactiveVal() })

  output$base_input <- renderRHandsontable({
    rhandsontable(
      data.frame(Inputs = sapply(varValues, function(x) x$data)),
      readOnly = FALSE,
      colHeaders = c('Inputs'),
      rowHeaders = paste0("Var ", LETTERS[1:numVars]),
      contextMenu = FALSE
    )
  })

  observeEvent(input$base_input, {
    newValues <- hot_to_r(input$base_input)$Inputs
    for (i in 1:numVars) {varValues[[i]]$data <- newValues[i]}
  })

  lapply(1:numVars, function(i) {
    varInputId <- paste0("var_", i, "_input")
    output[[varInputId]] <- renderRHandsontable({
      df <- data.frame(X = 1, Y = varValues[[i]]$data)
      rhandsontable(df, contextMenu = TRUE, minRows = 1,rowHeaders = FALSE) %>%
        onRender(jsCode) %>%
        hot_validate_numeric(col = 1, min = 1, max = input$periods)
    })
  })

  output$Vectors <- renderUI({
    lapply(1:numVars, function(i) {
      varInputId <- paste0("var_", i, "_input")
      list(
        h5(strong(paste】

结论

通过修改 beforeRemoveRow 挂钩,我们可以实现条件重置,以仅重置满足特定条件的 X/Y 表格。这对于防止用户意外删除数据并保持应用程序的完整性至关重要。

常见问题解答

  1. 为什么需要 beforeRemoveRow 挂钩?

    • beforeRemoveRow 挂钩允许我们在行被删除之前拦截和修改行为。在这种情况下,我们使用它来检查 X 列中的最大值并防止删除不符合条件的行。
  2. 如何自定义 beforeRemoveRow 挂钩?

    • beforeRemoveRow 挂钩可以通过 Handsontable.hooks.add('beforeRemoveRow', function(index, amount){...}) 函数进行自定义,其中 index 是要删除的行索引,amount 是要删除的行数。
  3. 如何使用 onRender() 函数修改 rhandsontable 实例?

    • onRender() 函数允许我们在 rhandsontable 实例渲染后执行自定义代码。在这里,我们使用它来应用 jsCode 修改,它包含我们自定义的 beforeRemoveRow 挂钩。
  4. 为什么我们需要 minRows = 1 选项?

    • minRows = 1 选项确保 X/Y 表格中始终至少有一行。这对于防止应用程序出现错误至关重要。
  5. 如何验证 X 列中的输入?

    • 我们可以使用 hot_validate_numeric() 函数来验证 X 列中的输入,该函数允许我们设置最小和最大允许值。