使用Validation API根据标准验证表单

一次,几乎每个人都喜欢Angular 2+,它是一个设计良好的框架,在工程性能方面领先于其他流行的前端框架。但是他也有非常奇怪的缺陷。其中之一是不可能手动调用表单的验证或重新验证,这种情况至少在第8版之前就被观察到。这并不是说他们非常喜欢反应性,但是在此子系统中,似乎一些反应性的考虑促使开发人员仅通过绑定来实现验证,从而迫使应用程序开发人员转向拐杖,例如将字段的状态设置为“未修改”,并使编写复杂的验证器和高级代码变得复杂化。逻辑和多个领域的参与。处理Angular验证程序和框架的其他功能的经历使我印象更加深刻,即使用HTML5 API进行表单验证之后,它变得多么优雅和简单,即使在不使用框架和库的情况下,它也可以在任何现代浏览器中“正常工作”。



元素属性是验证器的基础。使用属性,我们可以立即设置以下限制:

必填-必填字段,即需要填补

分钟 最大 -最小和最大允许值,以及改变的步骤

MINLENGTH个最大长度-在允许的输入字符数限制器

模式-正则表达式

这似乎不是很多,但是,模式为我们提供了用于检查值相当丰富的机会,规律很容易用Google搜索允许立即检查电话号码,电子邮件地址和URL,以及更多需求。

这些属性安排在表单元素上,不会自动允许从向服务器提交提交值的同一表单触发按钮,尽管今天这种情况对于许多人来说似乎已经过时了。但这不是问题,因为使用JavaScript客户端代码,我们可以以相同甚至更好的方式使用所有这些验证器。因此,我们将不使用输入类型= email,而是尝试在我们自己的字段中检查输入是否符合生成电子邮件地址的规则。让我们做一个简单的表格:

<form name="myform" id="myform">
   <input type="text" pattern="^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" placeholder="email here"/>
   <input type="submit">
</form>


验证器可立即工作,并在尝试按下按钮时,将以浏览器语言环境的语言发出警告。







因此,输入mail@example.com可以成功提交表单。

要开发您的行为,您需要访问表单实例,这可以通过全局文档按名称,索引(id)或从零开始的序数来完成。

<script type="module">
   document.forms.myform.onsubmit = (event) => {
       console.log('validate');
       return false;
   };
</script>


或由选择器使用以下方法之一(例如document.getElementById()document.querySelector())

检查结果,然后运行http-server

npx http-server


命令运行后,您可以在浏览器的控制台中打开127.0.0.1:8080 /或它写入您的地址,然后调试结果。



让我们用一个常规按钮替换Submit并手动调用表单验证,稍微更改一下示例。

<form id="myform" action="#">
   <input type="text" pattern="^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" required placeholder="email here" />
   <input type="button" name="subm" value="OK" />
</form>

<script type="module">;
   myform.subm.onclick = (event) => {
       console.log(form.checkValidity());
       return false;
   };
</script>


在此示例中,您可以看到按其ID和名称映射表单对象适用于与表单相关的子元素,这看起来非常优雅。现在,我们的代码将表单的有效性状态打印到控制台。

手动启动验证的方法的存在并不意味着无法调用验证就无法执行。

输入的结果和对表单的其他更改会立即反映在其状态中,这种状态表现为存在有效无效样式的伪类如果添加颜色突出显示,则可以看到验证如何立即进行。

<style>
  :valid {
       border: 1px solid green;
   }
  :invalid {
       border: 1px solid red;
   }
</style>








为了防止表单在用户尝试向其中输入内容之前用红色烦人,您可以使用带有占位符的生活技巧:

<style>
   input:valid {
       border: 1px solid green;
   }
   input:not(:placeholder-shown):invalid {
       border: 1px solid red;
   }
</style>


验证事件的外部处理程序可以挂在表单元素上。

<script type="module">
   myform.email.oninvalid = (event) => {
       alert('Wrong email !!11');
   };
   myform.subm.onclick = (event) => {
       console.log(form.checkValidity());
       return false;
   };
</script>


在这种情况下,事件的名称将使用钩子机制,如果元素支持某些事件,则通过为其分配一个以+ <event_name>命名的函数,我们可以确保在触发时将其调用。



还有一个更妙的一点是,当输入数据时将不再调用它们,而仅在以编程方式刺激验证时(即调用checkValidity()方法。



因此,我们可以处理以下行为:

myform.subm.onclick = (event) => {
   if (myform.checkValidity()) {
       alert('Valid !');
   } else {
       alert('Invalid !')
   }
   return false;
};


在现实生活中,如果验证未能中止表单提交过程,我们可能还需要调用event.preventDefault()



checkValidity()处是一个模拟reportValidity(),它返回结果而不会引起重新验证。



您怎么知道哪个字段是错误的?



每个表单输入元素都具有.validity属性,并具有在其上调用验证方法的能力,该属性具有以下结构:



ValueState:{

valid-

value正确性的一般符号Missing-该值是必需的,但未设置

typeMismatch-

输入的类型错误patternMismatch-引入值不匹配

tooLong-大于maxlength的

值tooShort-小于

minlength rangeUnderflow的值-小于min

rangeOverflow的值-step大于max的

值stepMismatch-值不匹配step

badInput-输入不能被

强制为value customError-任意错误

}



基本上,我们可以看到,错误属性对应于标准验证属性,而.customError是我们的扩展空间通过使用错误字符串作为参数

调用.setCustomValidity()方法,我们可以将表单元素标记为无效。您还可以通过.validationMessage属性设置或获取错误文本。...

为了不设置浏览器验证,可以使用.willValidate属性,该属性指示是否在字段上调用标准验证。

通过将空字符串作为参数传递给.setCustomValidity(),我们可以将其状态恢复为有效。

让我们添加对我们自己的my-pattern属性的支持,该属性将以相同的方式针对正则表达式检查该值,以使其更加清晰。

发生错误时,除浏览器中提供的消息外,该消息还将显示在该字段旁边,

当替换字段的值更改并按下按钮时,将触发验证。

<form id="myform" action="#">
   <div>
       <input type="text" name="email" id="email" value="" pattern="^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" required placeholder="email here" />
       <span class="msg"></span>
   </div>
   <div>
       <input type="text" name="customInput" id="customInput" my-pattern="^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" required placeholder="text here" />
       <span class="msg"></span>
   </div>
   <button type="submit" name="subm" value="OK">OK</button>
</form>
<style>
   input:valid {
       border: 1px solid green;
   }
   input:not(:placeholder-shown):invalid {
       border: 1px solid red;
   }
</style>
<script type="module">
   myform.customInput.oninvalid = (event) => {
       let el = event.target;
       let msg = el.parentElement.querySelector('.msg');
       msg.innerText = el.validationMessage;
       console.log('oninvalid, id: ', el.id);
   };
   myform.customInput.oninput = (event) => {
       let el = event.currentTarget;
       validateWithMyPattern(el);
       markValidity(el);
   };
   function markValidity(el) {
       el.checkValidity();
       let msg = el.parentElement.querySelector('.msg');
       if (el.validity.valid) {
           msg.innerText = '';
       } else {
           msg.innerText = el.validationMessage;
       }
   }
   function validateWithMyPattern(field) {
       if (field.value) {
           if (field.hasAttribute('my-pattern') &&
               field.value.match(field.getAttribute('my-pattern'))) {
               field.setCustomValidity('');
           } else {
               field.setCustomValidity('My pattern error');
           }
       }
   }
   myform.subm.onclick = (event) => {
       for (let formEl of myform.querySelectorAll('input')) {
           validateWithMyPattern(formEl);
           markValidity(formEl);
       }
       if (myform.reportValidity()) {
           alert('Valid !');
       } else {
           alert('Invalid !')
       }
       return false;
   };
</script>


现在,我们有两个类似的字段,它们使用标准验证器检查值,而我们自己编写了一个。







可能性似乎并不丰富,但是,借助它们,您可以实施任何验证,包括。领域的组,而不会像流行的框架那样在技术上受到限制。



在Validation API的限制中,我只记得字段的初始无效。为此,除了保留占位符或特殊状态a-la的技巧外,您还可以通过将自己的验证器与标准验证器结合使用,以编程方式对输入进行所有验证,并提交事件。

为了解决我的问题,我需要创建自己的组件来同时执行表单任务以支持我自己的输入元素,这允许您设置不同的验证和通知行为并挂起任何验证器并使用标准化的Validation API。您可以在这里看到它:https : //bitbucket.org/techminded/skinny-widgets/src/master/src/form/

,本文的示例代码可以在这里找到:https :

//bitbucket.org/techminded/myform /



All Articles