事件 - htmx:validation:failed

htmx:validation:failed 是 HTMX 在提交表单或发起请求前,当前端 HTML5 表单验证不通过时触发的事件。

当页面上的表单元素(如: input、textarea 等)因为页面设计的布局需要,无法使用 <form> 标签放在一起,但又想使用 H5 的表单验证功能时拦截该事件就变得非常必要及有用。

例如:

  • <input required>

  • <input type="email"> 无效

  • <input minlength="6"> 不满足

这些原生 HTML 表单验证失败,都会阻止请求,并触发 htmx:validation:failed。

事件参数

  • detail.elt - 触发请求的元素
  • detail.message - 验证错误消息
  • detail.validity - 有效性对象,包含指定验证失败情况的属性

触发时机

  • 当用户点击带 hx-post、hx-get 等属性的按钮或表单提交按钮

  • 并且表单中有字段未通过原生 HTML5 校验

  • HTMX 会阻止该请求,并触发 htmx:validation:failed 事件

示例代码

<form id="myForm" hx-post="/submit" hx-target="#result">
  <label for="email">邮箱</label>
  <input type="email" name="email" required placeholder="请输入邮箱">
  <button type="submit">提交</button>
</form>

<div id="result"></div>

<script>
  document.body.addEventListener("htmx:validation:failed", function(evt) {
    console.warn("表单校验失败!");
    evt.detail.errors.forEach(err => {
        let s = err.elt.name;
        const lbl = document.querySelector(`label[for="${s}"]`);
        if (lbl) {
            s = lbl.innerText;
        }
        if (err.validity.valueMissing) {
            flashMessage(`${s} 不能为空。`, "error");
        }
        if (err.validity.typeMismatch) {
            flashMessage(`请输入有效的 ${s}.`, "error");
        }
    });
    if (evt.detail.errors.length > 0) {
        const elt = evt.detail.errors[0].elt;
        if (elt) {
            elt.focus();
        }
    }
  });
</script>

上述示例代码中,如果用户点击“提交”按钮但 email 输入为空或格式错误,则请求不会发送且会触发:htmx:validation:failed 。

并且通过 event.detail 中带入的信息以及 <label> 标签,做成了一个通用的提示函数,该函数能够准确地提示未满足的表单项名称及原因,如提示:邮箱不能为空。同时会自动把焦点放在第一个出现错误的控件上。