【问题标题】:How to add/remove class and re-validate after form reset?表单重置后如何添加/删除类并重新验证?
【发布时间】:2020-11-14 21:33:30
【问题描述】:

我从here找到了这段代码:

$(document).ready(function() {
  var errorMessage = "Please match the specified format.";

  $(this).find("textarea").on("input change propertychange", function() {

    var pattern = $(this).attr("pattern");

    if (typeof pattern !== typeof undefined && pattern !== false) {
      var patternRegex = new RegExp("^" + pattern.replace(/^\^|\$$/g, '') + "$", "g");

      hasError = !$(this).val().match(patternRegex);

      if (typeof this.setCustomValidity === "function") {
        this.setCustomValidity(hasError ? errorMessage : "");
      } else {
        $(this).toggleClass("error", !!hasError);
        $(this).toggleClass("ok", !hasError);
        if (hasError) {
          $(this).attr("title", errorMessage);
        } else {
          $(this).removeAttr("title");
        }
      }
    }

  });


  $("#reset").click(function() {
    $("#form1").reset();
    if ($('[name ="textA5"]').hasClass("error")) {
      $("#form1").toggleClass("error");
    }
  });

});
.error {
  background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="form1" id="form1">
  <textarea name="textA5" rows="8" cols="80" wrap="off" pattern="^[A-Za-z0-9-_]{1,}$"></textarea>
  <span class="errMSG">You have an error. Check format.</span>
  <input class="buttons" type="reset" name="Reset" id="reset" value="Reset" />
  <input class="buttons" type="submit" value="Save Configuration" />
</form>

我有两个无法解决的问题。

  1. 我不知道如何使 textarea 的背景在出错时变为红色。我尝试以各种方式将 JQuery 的 .addClass 和 .css 添加到代码中,但我无法让它工作。我还想切换文本区域框下方错误消息的可见性。
  2. 我有一个表单的重置按钮,它可以工作,但是重置后它不会清除错误状态。我假设重置后必须重新验证表单。如何让重置按钮重置表单并在表单重置后重新验证?

【问题讨论】:

  • 在 CSS 设置类 .error { background-color: red } 或做其他讨厌的事情...(即 .error)。重置按钮:如果 textarea 包含 .errortoggleClass("error")
  • @Rene van der Lende - 我在 OP 中编辑了代码,但仍然无法正常工作。
  • 新代码错误:$("#form1")[0].reset(); => 'reset' 不是函数。不过,textarea 有一个红色边框。
  • 请发布一些被认为不适合测试的文本.....
  • 若要验证失败,请输入任何特殊字符(例如 =、*、%)

标签: jquery css validation


【解决方案1】:

您的“错误”机制未正确触发,您调用了一个不存在的函数:“reset()”。

我将切换代码移到了一个单独的函数中,以便可以随时调用它,参数:

  • element 需要切换
  • hasError 是否出错(真/假)
  • msg要显示的错误信息

[重置]-按钮将显示/隐藏任何“红色”... 仅出于测试目的,我将光标重新定位在 textarea 的开头。

更新

按照承诺对原始代码进行一些更改

  • 我添加了添加辅助错误文本元素(在您的情况下为 .errMSG)的可能性,包括一些 CSS 以在 &lt;textarea&gt; 具有 .error 时隐藏/显示消息。
  • Javascript 现在会重置所有设置了.error 的元素(不仅是&lt;textarea&gt;)。
  • 更正了空&lt;textarea&gt; 仍可能触发错误的错误。
  • 添加了一些有用的 cmets

警告:Javascript 必须打包在一个函数中,并且不仅在document.ready() 上运行,而且在用户刷新页面后运行。目前,当&lt;textarea&gt; 出现错误并且用户点击 [F5](刷新页面)时,错误状态会被重置,但不会针对仍然存在的数据运行。

更新2

使 JS 代码更通用,现在处理所有定义了 [pattern] 的元素。在 JS 中重新引入了 HTML 默认的“有效性检查”。扩展 HTML 和 CSS 以反映/测试更改。

'use-strict';

//<!--
$( document ).ready( function() {
    var errorMessage = "Please match the specified format.";

    // find all textareas in this form and attach enventlisteners
    $( this ).find( "[pattern]" ).on( "input change propertychange", function() {

        var pattern = $( this ).attr( "pattern" );

        // when the <textarea> regex pattern 
        if(typeof pattern !== typeof undefined && pattern !== false)
        {
            var patternRegex = new RegExp( "^" + pattern.replace(/^\^|\$$/g, '') + "$", "g" );

            // (corrected emtpy) <textarea> will now be in error when only not empty && fails regex
            var hasError = (!$( this ).val() == "" &&  !$( this ).val().match( patternRegex ));

            // toggle error state for this <textara>
            toggleError(this, hasError, errorMessage);
        }
    });

    $("#reset").click(function() {
        $('.error').each(function( index ) {
            toggleError(this, false, ""); // remove error state and
            // $(this).val(""); // empty the 'value' attribute
            // [OPTIONAL] as button [type="reset"] already empties form field values
        });
        // $('[name^="textA"]')[0].focus(); // [OPTIONAL] repositions cursor to topmost
    }); 

    function toggleError(elem, hasError, msg) {
        if (typeof elem.setCustomValidity === "function") {
            elem.setCustomValidity(hasError ? msg : ""); };

        // if in error assign msg otherwise blank
        elem.setAttribute( "title", (hasError) ? msg : "" );

        // if in error add class, otherwise remove it
        (hasError) ? $(elem).addClass('error') : $(elem).removeClass('error');
    };
});
//-->
.error              { background-color: red }
.errMSG             { display: none }
.error+.errMSG      { display: initial }

:invalid,           /* remove default red borders */
:-moz-ui-invalid    { box-shadow: none; outline: none }

/* eye-candy/demo only */
/* <textarea> can't handle 'position: relative', but <div> can */
.area-container     { position: relative; padding-bottom: 4rem }
.error+.errMSG      { position: absolute; bottom: 2rem; left: 0 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<form name="form1" id="form1">
    <div class="area-container">
        <textarea name="textA5" rows="8" cols="80" wrap="off" pattern="^[A-Za-z0-9-_]{1,}$"></textarea>
        <span class="errMSG">You have an error. Check TEXTA5 format.</span>
    </div>
    <div class="area-container">
        <input type="text" pattern="^[A-Za-z0-9-_]{1,}$">
        <span class="errMSG">You have an error. Check TEXT1 format.</span>
    </div>
    <div class="area-container">
        <textarea name="textA6" rows="8" cols="80" wrap="off" pattern="^[A-Za-z0-9-_]{1,}$"></textarea>
        <span class="errMSG">You have an error. Check TEXTA6 format.</span>
    </div>        
    <div class="area-container">
        <input type="text" pattern="^[A-Za-z0-9-_]{1,}$">
        <span class="errMSG">You have an error. Check TEXT2 format.</span>
    </div>
    <input class="buttons" type="reset" name="Reset" id="reset" value="Reset" />
    <input class="buttons" type="submit" value="Save Configuration" />
</form>

【讨论】:

  • 谢谢!我仍在尝试将其实现为我的实际形式。在我的 HTML 中,我有额外的 span 标签,其中包含错误消息。默认情况下,它们是 display:none。触发验证错误时,我应该在哪里添加什么代码来切换可见性?我在我的 OP 中的 HTML 代码中添加了一个示例。
  • @Jeff,您可以使用 CSS .errMSG { display: none } .error+.errMSG { display: initial },但这需要一些额外的 JS,因为现在只针对 name="textA5"。但请注意,您的 OP 问题目前已经解决。我也在努力解决第二个问题,稍后会发布更新,但我认为接受任何一个答案都是公平的。
  • 感谢您的更新。我真的很感谢你抽出时间。与原来的不同,即使模式不匹配,现在似乎也可以提交更新的表单。如果模式不匹配,如何禁止表单提交?
  • 问题在于 &lt;textarea&gt; 不像 &lt;input&gt; 元素那样处理 [pattern] (并且由内置错误处理和 JS 函数的浏览器/W3C 管理) checkValidity()setCustomValidity())。将&lt;input type="text" pattern="^[A-Za-z0-9-_]{1,}$"&gt; 添加到您的 HTML 中,您可以看到该机制在起作用。不需要 JS。也许我误解了setCustomValidity 的用法(并删除了它)。我将对此进行深入研究,并在必要时重新介绍它。
  • @Jeff 这确实是我删除的setCustomValidity 检查,所以我重新引入了它。我还用一些额外的&lt;input with pattern&gt; 扩展了sn-p,以表明JS 检查所有使用[pattern](不仅是&lt;textarea&gt;)的输入元素。结帐 update2
【解决方案2】:
  1. 你需要在里面添加你的$(this).toggleClass("error", !!hasError); 你的 if (typeof this.setCustomValidity$(".errMSG").toggle(!!hasError); 用于错误跨度按摩(不要忘记 .errMSG display:none 的 css 类)

  2. 要删除所有错误并重置表单,请使用它(注意它有 .setCustomValidity(''))以及从文本区域中删除类:

    $("#reset").click(function() { if ($('[name ="textA5"]').hasClass("error")) { $('[name ="textA5"]')[0].setCustomValidity(''); $('[name ="textA5"]').removeClass("error").val(""); $(".errMSG").hide(); } });

工作:

<!--
$(document).ready(function() {
  var errorMessage = "Please match the specified format.";

  $(this).find("textarea").on("input change propertychange", function() {

    var pattern = $(this).attr("pattern");

    if (typeof pattern !== typeof undefined && pattern !== false) {
      var patternRegex = new RegExp("^" + pattern.replace(/^\^|\$$/g, '') + "$", "g");

      hasError = !$(this).val().match(patternRegex);

      if (typeof this.setCustomValidity === "function") {
        this.setCustomValidity(hasError ? errorMessage : "");
        $(this).toggleClass("error", !!hasError);
        $(".errMSG").toggle(!!hasError);        
      } else {
        $(this).toggleClass("ok", !hasError);
        if (hasError) {
          $(this).attr("title", errorMessage);
        } else {
          $(this).removeAttr("title");
        }
      }
      if ($(this).val()==""){
      //console.log(true)
        $('[name ="textA5"]')[0].setCustomValidity('');
        $('[name ="textA5"]').removeClass("error").val("");
        $(".errMSG").hide();}
    }

  });


  $("#reset").click(function() {
    if ($('[name ="textA5"]').hasClass("error")) {
      $('[name ="textA5"]')[0].setCustomValidity('');
      $('[name ="textA5"]').removeClass("error").val("");
      $(".errMSG").hide();
    }
  });



});
//-->
.error {
  background-color: red;
  outline: none;
}
.errMSG {
display: none}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>

<head>
  <script src="includes/jquery-3.5.1.min.js"></script>

</head>

<body>
  <form name="form1" id="form1">
    <textarea name="textA5" rows="8" cols="80" wrap="off" pattern="^[A-Za-z0-9-_]{1,}$"></textarea>
    <span class="errMSG">You have an error. Check format.<br></span>
    <input class="buttons" type="reset" name="Reset" id="reset" value="Reset" />
    <input class="buttons" type="submit" value="Save Configuration" />
  </form>


</body>

</html>

编辑: 在更改事件结束时添加此 if 条件以解决文件被清空的问题(请参阅 sn-p)。

if ($(this).val()==""){
      //console.log(true)
        $('[name ="textA5"]')[0].setCustomValidity('');
        $('[name ="textA5"]').removeClass("error").val("");
        $(".errMSG").hide();}
    }

【讨论】:

  • 嗨@ikiK,我一直在查看您最近的更改,只是为了比较,我注意到当textarea 被清空时( [Backspace] 直到它再次为空,或者删除内容[Ctrl-A,Ctrl-X] ),然后该字段变为红色。 regex 出了点问题,因为我的解决方案遇到了同样的问题...用.removeAttr('value') 删除value 并不能解决问题。
  • @RenevanderLende 查看上次编辑。我不知道问题出在哪里,但我添加了 if 语句来解决这个问题。
猜你喜欢
  • 1970-01-01
  • 2015-04-20
  • 1970-01-01
  • 2014-05-30
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
  • 2011-06-06
相关资源
最近更新 更多