我开始使用hot_validate_numeric()个rhandsontable包,事实证明它对用户输入验证非常有用.根据下面的MWE代码,用户只能输入范围从1到10的数值,如果用户输入的值超出了这个范围,或者输入了字母字符或其他无意义的输入,表将很好地拒绝输入并冻结,直到用户使用正确的形式输入值.当用户更改现有单元格或添加行时,这会起作用.这太完美了!

然而,我如何扩展它,以便验证判断也适用于:(1)对单元格的任何输入都必须大于其上一个紧邻的单元格中的值(第一个单元格除外),以及(2)只能输入整数(没有小数值)?理想情况下,响应将与使用hot_validate_numeric(...)时相同,因为输入被拒绝,单元格冻结,直到用户使用正确的顺序输入值.

可能是因为rhandsontable不支持基于表中其他单元格的值直接到hot_validate_numeric()的动态验证,我不确定.

我已经玩了hot_validate_numeric(col = 1, choices = c(...))个,但似乎不起作用,将通过GitHub提交错误报告.

library(rhandsontable)
library(shiny)

DF <- data.frame(X = c(1,3,5,7,10))

ui <- fluidPage(
  rHandsontableOutput("base_input")
)

server <- function(input, output, session) {
  output$base_input <- renderRHandsontable({
  rhandsontable(DF) %>%  hot_validate_numeric(col = 1, min = 1, max = 10)
  })
}

shinyApp(ui, server)

推荐答案

验证器是一个JavaScript函数,它只接受要验证的值作为输入,因此不允许将该值与另一个单元格的值进行比较.

要仅验证整数值,可以稍微修改hot_validate_numeric.这就是我所做的(但我没有测试):

hot_validate_integer <- function (hot, cols, min = NULL, max = NULL, choices = NULL, 
          exclude = NULL, allowInvalid = FALSE) 
{
  f <- paste(
    "function (value, callback) {",                              
    "  if (value === null || value === void 0) {",               
    "    value = '';",                                       
    "  }",                                                       
    "  if (this.allowEmpty && value === '') {",              
    "    return callback(true);",                                
    "  } else if (value === '') {",                          
    "    return callback(false);",                               
    "  }",                                                       
    "  let isNumber = /^-?\\d*(\\.|,)?\\d*$/.test(value);",
    "  if (!isNumber) {",                                        
    "    return callback(false);",                               
    "  }",
    "  let x = parseFloat(value);",
    "  if (isNaN(x) || !Number.isInteger(x)) {",                         
    "    return callback(false);",                               
    "  }",                                                       
    "  %exclude",                                                
    "  %min",                                                    
    "  %max",                                                    
    "  %choices",                                                
    "  return callback(true);",                                  
    "}",
    sep = "\n"
  )
  if (!is.null(exclude)) 
    ex_str = paste0("if ([", paste0(paste0("'", exclude, 
                                           "'"), collapse = ","), "].indexOf(value) > -1) { return callback(false); }")
  else ex_str = ""
  f = gsub("%exclude", ex_str, f)
  if (!is.null(min)) 
    min_str = paste0("if (value < ", min, ") { return callback(false); }")
  else min_str = ""
  f = gsub("%min", min_str, f)
  if (!is.null(max)) 
    max_str = paste0("if (value > ", max, ") { return callback(false); }")
  else max_str = ""
  f = gsub("%max", max_str, f)
  if (!is.null(choices)) 
    chcs_str = paste0("if ([", paste0(paste0("'", choices, 
                                             "'"), collapse = ","), "].indexOf(value) == -1) { return callback(false); }")
  else chcs_str = ""
  f = gsub("%choices", chcs_str, f)
  for (x in cols) hot = hot %>% hot_col(x, validator = f, allowInvalid = allowInvalid)
  hot
}

Edit: it's possible!

最后,可以使用afterValidateCell钩子与上面的单元格进行比较:

jsCode <- c(
  "function(el, x) {",
  "  var hot = this.hot;",
  "  Handsontable.hooks.add('afterValidate', function(isValid, value, row, prop){",
  "    if(row > 0) {",
  "      let x = this.getDataAtCell(row - 1, prop);",
  "      if(value < x) {",
  "        return(false);",
  "      }",
  "    }",
  "  }, hot);",
  "}"
)

library(rhandsontable)
library(htmlwidgets)

MAT = matrix(seq_len(50), nrow = 10, dimnames = list(LETTERS[1:10],
                                                   letters[1:5]))

rhandsontable(MAT) %>%
  hot_validate_integer(col = 1) %>% 
  onRender(jsCode)

Javascript相关问答推荐

Express.js:使用Passport.js实现基于角色的身份验证时出现太多重定向问题

在JavaScript中对大型级联数组进行切片的最有效方法?

字节数组通过echo框架传输到JS blob

将2D数组转换为图形

Msgraph用户邀请自定义邮箱模板

在grafana情节,避免冲突的情节和传说

如何在 cypress 中使用静态嵌套循环

使用ThreeJ渲染的形状具有抖动/模糊的边缘

如何使用JavaScript拆分带空格的单词

未捕获的运行时错误:调度程序为空

如何根据查询结果重新排列日期

React Refs不与高阶组件(HOC)中的动态生成组件一起工作

如何在Java脚本中并行运行for或任意循环的每次迭代

表单数据中未定义的数组键

重新渲染过多(&Q).REACT限制渲染次数以防止无限循环.使用REACT下拉菜单时

如何在Reaction中设置缺省值, Select 下拉列表,动态追加剩余值?

无法在Adyen自定义卡安全字段创建中使用自定义占位符

我如何才能让p5.js在不使用实例模式的情况下工作?

REACT-本机错误:错误类型错误:无法读取未定义的容器的属性

使用JAVASCRIPT-使用If和Else If多次判断条件-使用JAVASRIPT对象及其属性