【问题标题】:Best JavaScript solution for client-side form validation and interaction? [closed]客户端表单验证和交互的最佳 JavaScript 解决方案? [关闭]
【发布时间】:2011-06-12 17:08:06
【问题描述】:

我们的网络表单非常复杂。什么是可扩展表单验证的绝佳解决方案,最好是使用 jQuery 的解决方案?

背景:

我们的网站有一点 Ajax,但真正的重点是通过大约 20 个多页表单或“向导”来提供用户体验。这些表格很复杂。

  • 演示文稿:有些字段是浮点数或整数。验证意味着去除非十进制字符,但我们还想确保,如果用户在价格字段中输入 5,该字段会更新为 5.00
  • 副作用:某些字段在更新时会产生副作用。例如,更新商品的价格或数量需要更新小计字段。
  • 小部件驱动的元素: 一些字段是隐藏的,并且具有由小部件填充的值。例如,地图小部件可让您指向某个位置,隐藏字段会使用经纬度坐标进行更新,但该位置必须位于特定区域内。
  • 组:有些字段是组,例如地址/城市/州/邮编,只有在所有字段都已填充后才应进行验证。
  • 服务器端验证:某些字段的验证需要通过 Ajax 请求进行后端检查
  • 每页多个表单:有时用户需要先填写一个表单,然后才能打开另一个表单的对话框。框架必须比绑定到onSubmit 更通用——我们有时使用 Ajax 从同一页面按顺序发布多个表单。 (例如,我们让用户注册并一口气创建一个小部件,但由于遗留系统,该流程需要两个 POST 请求。)
  • 可自定义的错误显示:有时错误会出现在字段上方,有时字段样式会发生变化,我们的新设计需要类似工具提示的弹出窗口(ala qTip)来解决一些错误。
  • 活泼:用户体验是关键,触觉反馈很重要。任何解决方案
  • 提交按钮:单击提交按钮需要验证所有内容,然后显示响应 - 但由于某些验证是异步进行的。

我们目前正在使用jQuery Validation 库,但我们的表单似乎超出了它的能力。我一直在研究<angular/>KnockoutBackbone.js 之类的东西,但我担心它们太重了,或者它们会要求我们重写前端。

(这应该是一个社区 wiki。)

【问题讨论】:

  • 我很好奇这句话背后的真正含义,“我们的表单似乎超出了它的 [jQuery Validation Plugin] 能力”。你可以解释吗?很多人都在使用它,因此提供有关这些假定限制的更多详细信息可能对其他人很有教育意义。
  • 我们放弃它已经一年多了,所以我不记得整个故事了。我记得 IE7 存在错误(我们 7% 的用户仍在使用)。设置代码比 jQuery 工具更冗长和意大利面条。 jQuery Tools 的错误和工具提示定制要容易得多,而且通常具有良好的 API 和良好的文档。使用 jQuery 工具将基于 XHR 的验证集成到表单流中也更容易。
  • 尝试验证 jquery 插件。似乎很有希望。这是使用该插件的完整指南。 valijate.com/Docs.php

标签: javascript jquery html validation forms


【解决方案1】:

这是一个无耻的插件,但我可以自愿提供我设计的framework 吗?我已经基于注释(一个 la Hibernate Validator)构建了它。它支持自定义约束,我觉得它非常强大。 Here 也是一个 Stackoverflow 问题,我要求对框架进行审查。

  • 演示文稿:使用自定义验证约束,您可以将验证绑定到 onChange 元素。此外,由于 Regula 支持自定义验证器,您可以让自定义验证器更新字段的值(因此将 5 更改为 5.00)。
  • 副作用:Regula 通过自定义约束验证器支持副作用。
  • :Regula 支持验证组。您可以针对特定组进行验证。通过组合自定义验证器和组,您可以控制验证器的行为,以便它仅在该组的所有元素都被填充时验证 (尽管您必须通过普通 Javascript 执行此检查) .
  • 服务器端验证:使用自定义约束,您可以进行 AJAX 调用来执行服务器端验证。以目前框架的结构方式,这必然是一个阻塞的 ajax 调用。我计划在未来添加异步功能。
  • 每页多个表单:Regula 不限于每页验证一个表单。它可以处理多种形式(不确定我是否正确理解了您的要求 - 所以我可能没有正确回答这部分)。
  • 可自定义的错误显示:就验证而言,Regula 不会对页面的 UI 做任何事情。当您验证时,您会得到一组包含错误消息等的约束违规。如何显示它们取决于您。
  • Snappiness:我没有执行任何基准测试,因此我无法评论我的框架在这​​方面的表现。
  • 提交按钮:这是我尚未解决的问题(异步与同步)。

这里有几个例子:

以下显示了标准验证,带有内置约束:

<input id = "myInput"
       name = "myInput"
       type = "text"
       class = "regula-validation"
       data-constraints = '@NotEmpty @IsNumeric @Between(min=1, max=5)' />

jQuery(document).ready(function() {
    // must call regula.binnd() first. The best place would be in an
    // onload handler. This function looks for elements with
    // a class name of "regula-validation" and binds the
    // appropriate constraints to the elements

    regula.bind(); 

    jQuery("#myForm").submit(function() {
        // this function performs the actual validation
        var validationResults = regula.validate();

        for(var index in validationResults) {
             var validationResult = validationResults[index];
             alert(validationResult.message);
        }
    });
});

如您所见,您只处理违反约束的情况,因此显示错误消息的方式完全取决于您。

这是一个自定义约束的示例:

regula.custom({
   name: "MustBe42",
   defaultMessage: "The answer must be equal to 42",
   validator: function() {
      return this.value == 42;
   }
});

及其用途:

<input id = "theAnswerToLifeTheUniverseAndEverything" 
       name = "theAnswerToLifeTheUniverseAndEverything" 
       value = ""
       class = "regula-validation"
       data-constraints = "@MustBe42" />

由于验证器是一个 Javascript 函数,你可以让它做任何事情(所以这解决了你关于副作用的问题)。

这是另一个接受参数的约束的示例:

regula.custom({
   name: "DivisibleBy",
   defaultMessage: "{label} must be divisible by {divisor}",
   params: ["divisor"],
   validator: function(params) {
      var divisor = params["divisor"];
      return (this.value % divisor) == 0;
   }
});

及用法:

<input id = "number" 
       name = "number" 
       value = ""
       class = "regula-validation"
       data-constraints = "@DivisibleBy(divisor=3, label='The Number')" />

以下是使用验证组的示例:

<input id = "score"
       name = "score"
       type = "text"
       class = "regula-validation"
       data-constraints = '@IsNumeric(label="Score", 
                                      message="{label} needs to be a number!"
                                      groups=[FirstGroup, SecondGroup, ThirdGroup]' />

<input id = "age"
       name = "age"
       type = "text"
       class = "regula-validation"
       data-constraints = '@IsNumeric(label="Age", 
                                      message="{label} needs to be a number!"
                                      groups=[SecondGroup]' />

<input id = "name"
       name = "name"
       type = "text"
       class = "regula-validation"
       data-constraints = '@NotEmpty(label="Name", 
                                     message="{label} cannot be empty!"
                                     groups=[FirstGroup]' />

还有一个仅验证 FirstGroup 的 sn-p(因此仅验证 scorename):

var constraintViolations = regula.validate({groups: [regula.Group.FirstGroup]});
var messages = "";

for(var index in constraintViolations) {
      var constraintViolation = constraintViolations[index];
      messages += constraintViolation.message + "\n";
}

if(messages != "") {
   alert(messages);
}

如果您打算尝试一下,我建议您下载版本 1.1.1。当前文档专门匹配该版本。在 1.2.1 中,我添加了对复合约束的支持,但我没有更新我的文档以反映这一点。

我了解这是否不能解决您的所有问题,或者这不是您想要的。我以为我会把它放在那里。此外,如果您确实检查了它,那么我将确保更新文档以反映版本 1.2.1。我一直忙于学习和工作,所以我没有时间这样做。

更新 #1

Sohnee 提到了客户端验证。我实际上正在研究 Regula 和 Spring 3 之间的集成。希望我能够很快发布它(再次取决于工作和学校)。该集成通过将 Hibernate 验证约束转换为 Regula 验证约束来工作。这样,您只需(大部分)编写一次验证代码。但是,对于自定义约束,您仍然必须在 Javascript 端(自定义验证器)编写代码。但是一旦你用 Hibernate 验证约束在服务器端注释代码,你就不需要在客户端做任何事情了。这些约束会自动应用于客户端的表单元素。

Matthew Abbott 也可以integrate Regula with ASP.NET MVC

更新 #2

我有一个演示 webapp(mavenized)on github,它展示了 Regula 和 Spring 3.0.x Web MVC 之间使用 Hibernate Validator 的集成。它没有真正的记录或任何东西,它更多的是概念验证。我计划在 github 页面上添加一些关于集成及其工作原理的文档。

更新 #3

我已经更新了wiki 上的文档,现在它对应于最新版本,1.2.2(我做了一些小错误修复,这就是为什么它是 1.2 .2 现在)。

【讨论】:

  • 哇,如果你要投反对票,至少有礼貌地解释一下原因。我什至通过说这是一个无耻的插件来限定这个答案。说真的。
  • 看起来像是 fValidate 的精神继承者(顺便说一句,这不是我的反对意见)
  • +1 获取详细答案。听起来你的框架做了很多提问者所问的事情。
  • 答案写得好!我目前正在研究 jQuery UI 表单小部件以及添加验证模块的可能性,您的框架看起来是一个很好的灵感来源!
  • +1 用于满足轻量级需求(约 27kb 缩小对于这么多有趣的功能非常有用)。
【解决方案2】:

我已经多次将这个jQuery formValidator 与一大堆不同的环境结合使用。我希望它会有所帮助,因为我很少花费超过一个小时来设置它。

干杯!

【讨论】:

    【解决方案3】:

    我想说jQuery Validation 插件做得很好。我将它与metadata 插件结合使用,将服务器端验证参数传递给客户端。我还为所有表单包装了一些关键点,以便我可以使用通用模式进行验证,以及一些异常/自定义状态。这包括自定义警报消息和显示。

    它并不能满足您开箱即用的所有需求,但它是我见过的最佳选择和最佳默认行为。同样,我确实使用了元数据(属性“data-meta”)。它可以按照你的意愿弯曲。我还使用元数据将控件绑定到客户端的输入元素。这将我的客户端逻辑与服务器端分开,但从长远来看比尝试从服务器端逻辑注入 js 更容易。

    【讨论】:

      【解决方案4】:

      Parsley.js 在撰写本文时(2013 年 8 月)看起来是一个不错且受欢迎的选择。

      【讨论】:

      • 欧芹是我推荐给我的开发人员的。
      • Parsley 在撰写本文时非常棒,但他们的新版本的用户体验很差。其他人也发现了这个?
      【解决方案5】:

      我自己回答这个问题,因为我们团队中有人注意到了Validator from jQuery Tools

      • 演示文稿 - 支持 HTML5 输入字段。 pattern 字段确保用户只能以特定模式输入测试。
      • 副作用 - 在表单和各个字段上触发事件:onFailonSuccess
      • 小部件驱动元素 - 鼓励使用“自定义输入类型”。基本演示甚至包括一个自然数旧的“年龄”字段。
      • - 编写一个“函数匹配器”,其唯一目的是过滤要验证的字段。
      • 服务器端验证 - 是否智能地执行 - 取决于您的验证器调用回调(因此它是异步友好的)而不是返回值。
      • 每页多个表单 - jQuery 工具似乎构建得非常好,这应该不是问题。
      • 可自定义的错误显示 - 字段旁边的错误?都在一个地方?没问题。还是不够好?失败时绑定事件。甚至默认使用工具提示。
      • 活泼 - 演示非常活泼
      • 提交按钮 - 没问题。

      更新: 是的,刚刚使用 jQuery Tools 的验证器工具提示重新实现了我们网站的一部分。太棒了!

      【讨论】:

      • 太糟糕了,这被接受为答案。在我看来,jQuery 工具是一团糟,需要彻底检修。开发人员自己承认,已经对维护项目失去了兴趣,并且 6 个多月来一直未能找到愿意接管该项目的程序员。我的建议是远离这个答案,并使用very excellent plugin developed by a member of the jQuery team
      • 我接受了这个答案,因为 jQuery 工具尽管有点被忽视,但仍然是最好的,因为它支持 HTML5,与 IE7 和 IE9 兼容,并且易于重用(我们在网站范围内设置了行为默认值)和验证者)。三年来,bassistance.de Validator 插件一直是痛苦的根源,我们已尽一切努力将其删除。
      • 我完全不同意,但这不是这些 cmets 讨论的内容。
      • 我没有尝试过 jQuery 工具验证,但是 bassistance 验证器也让我很沮丧。
      • 这个库好像缺少支持
      【解决方案6】:

      服务器端验证非常棒。

      如果您愿意,可以通过 AJAX 请求提供此类验证的结果...或使用服务器端框架,该框架也将添加客户端验证 - 但不要重复编写。

      【讨论】:

      • 为什么不同时验证客户端和服务器以提高安全性?还是那是多余的?我想问题是为什么'不要写两次'
      • 我相信我建议同时进行服务器端和客户端验证 - 但使用将生成客户端验证的服务器端框架。为什么?因为您不应该发现自己必须更改邮政编码的“服务器”验证,然后更改邮政编码的“客户端”验证。将一条规则放在一处使您的代码可维护。
      • 我正在将 Spring 集成到 Regula。虽然我还没有发布它,但我已经找到了一种将 Hibernate Validation Constraints 转换为客户端的 Regula 约束的方法。这样,您大部分情况下必须执行一次验证。
      • 仅使用服务器端验证的问题在于,当它被使用的频率与原始问题表明的一样频繁时,您基本上每个验证事件都使用一个 http 连接。所以,是的,如果你这样做,你可能会坚持 DRY,但你需要权衡一下,与在每个表单提交结束时有更多的连接访问服务器/网络而不是必要的连接所带来的开销。
      • @whaley - 不要忘记许多框架会自动将您的服务器端验证转换为客户端验证。这个想法是,编写一次,然后让框架为您进行完全客户端验证。例如,ASP.NET MVC 使用模型上的属性来进行服务器端和客户端验证,因此您只需维护一个属性,而不是在多种语言/地方重复验证。
      【解决方案7】:

      使用 jQuery 验证插件。到目前为止,它从来没有让我失望过

      【讨论】:

        【解决方案8】:
         function isEmpty(text) {
        if(text == undefined) {
            return true;
        }
        if(text.replace(/\s+/g, ' ').length == 0) {
            return true;
        }
        return false;
        }
        
        function isValidBoolean(text) {
           if(text == undefined || (text.toLowerCase() != "true" &&    text.toLowerCase() != "false")) {
            return false;
        }
        return true;
         }
        
          function isValidDouble(text) {
             var out = parseFloat(text);
           if(isNaN(out)) {
            return false;
          }
          return true;
          }
        
          function isValidLong(text) {
        var out = parseInt(text);
        if(isNaN(out)) {
            return false;
        }
        return true;
        }
        
         function isValidDate(text) {
        if(Date.parseString(text, 'MM/dd/yyyy HH:mm:ss') == null) {
            return false;
        }
        return true;
        }
        
          function hasDuplicates(array) {
        var valuesSoFar = {};
        for (var i = 0; i < array.length; ++i) {
            var value = array[i];
            if (Object.prototype.hasOwnProperty.call(valuesSoFar, value)) {
                return true;
            }
            valuesSoFar[value] = true;
        }
        return false;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-04
          • 2013-10-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多