我時常聽到對 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中文網其他相關文章!