我时常听到对 htmx 的批评,说它不擅长处理错误。我将举一个例子来说明为什么我认为情况并非如此。 htmx 的常见操作之一是将 HTML 表单(类型为 application/x-www-form-urlencoded)提交到后端服务器并获取响应。当然,最好的方法是响应成功并且 htmx 进行 HTML 片段交换。但让我们看看悲伤的道路。
常见的用户体验需求是在每个验证失败的字段旁边显示错误消息。查看 Bulma CSS 框架文档中的示例:https://bulma.io/documentation/form/general/#complete-form-example
这看起来确实不错...但它还需要为每个字段提供自定义标记和布局。如果我们利用现代浏览器对 HTML 约束验证 API 的支持会怎样?这允许我们将错误消息附加到每个字段,并使用其自己的弹出窗口,该弹出窗口位于外部文档的标记。您可以在此处查看示例:https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/reportValidity#results
如果每个验证失败的字段都弹出这样的消息怎么办?这就是这篇文章的问题。
假设您有一个端点 POST /users,它处理负载 fullname=Foo&email=bar@baz.com 的表单。您在后端获取数据,对其进行解码,如果成功,您就走上了前面提到的幸福之路。但如果表单解码失败,我们就会遇到有趣的事情。
这里是关键点:如果表单解码失败,您需要某种方式让 htmx 知道这个特定错误,而不是可能发生的其他错误。我们需要在这里做出决定。假设我们对验证失败的表单使用 422 Unprocessable Content 状态代码。
现在,我们需要决定如何格式化验证错误消息。前面提到的约束验证 API 是一个 JavaScript API,因此它几乎为我们做出了决定。我们将错误格式化为 JSON。
这是一个示例表单:
<form id=add-user-form method=post action=/users hx-post=/users > <input name=fullname> <input type=email> <input type=submit value="Add User"> </form>
当然,在真实的应用程序中,这两个输入都具有必需的属性;在这里,我只是出于演示目的而将它们排除在外。
如果我们提交此表单时全名和电子邮件字段留空,那么后端应该无法验证该表单并响应以下内容:
HTTP 422 Content-Type: application/json { "add-user-form": { "fullname": "Please fill out this field", "email": "Please fill out this field" } }
我们如何实现这一目标?嗯,htmx 发送一个请求标头 HX-Trigger,其中包含触发元素的 id,在本例中为 add-user-form。所以我们从那里获取最外层对象的密钥。然后,我们的表单验证函数应该告诉我们验证失败的字段的名称以及每个字段的错误消息。这为我们提供了带有键和值的内部对象。
通过后端的响应,我们需要一些 JavaScript 来遍历 JSON 并将错误消息附加到每个相应的表单字段。
document.addEventListener('htmx:responseError', evt => { const xhr = evt.detail.xhr; if (xhr.status == 422) { const errors = JSON.parse(xhr.responseText); for (const formId of Object.keys(errors)) { const formErrors = errors[formId]; for (const name of Object.keys(formErrors)) { const field = document.querySelector(`#${formId} [name="${name}"]`); field.setCustomValidity(formErrors[name]); field.addEventListener('focus', () => field.reportValidity()); field.addEventListener('change', () => field.setCustomValidity('')); field.focus(); } } } else { // Handle the error some other way console.error(xhr.responseText); } });
我们在这里做三件关键的事情:
上面的第四个操作虽然不重要,但却是一个很好的选择:我们专注于其中一个字段以使其弹出错误消息。这向用户表明表单提交出现了问题。当然,您可以提供更大的提示,例如通过定位 input:invalid 伪选择器,使用 CSS 突出显示处于无效状态的输入。
现在,只要提交表单并且出现验证错误,响应就会自动将错误消息填充到正确的位置。
如果您一直密切关注,您可能会认为这种技术似乎不仅限于 htmx – 您是对的!这种基于约束验证 API 的技术可用于任何使用表单的前端。它不需要专门与 htmx 一起使用。您只需要对其进行调整以处理来自后端服务器的表单验证错误。
通过利用现代浏览器的内置功能,我们使代码更具适应性,并受益于浏览器对其 UI 的未来改进。
以上是处理 htmx 中的表单错误的详细内容。更多信息请关注PHP中文网其他相关文章!