自定义确认 UI

htmx 支持 hx-confirm 属性,提供一种简单的机制来确认用户操作。这使用 JavaScript 中的默认 confirm() 函数,虽然可靠,但可能与您的应用 UX 不一致。

在本示例中,我们将看到如何使用 sweetalert2 来实现自定义确认对话框。下面有两个示例,一个使用 click+自定义事件方法,另一个使用内置的 hx-confirm 属性和 htmx:confirm 事件。

使用 click+自定义事件

<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<button hx-get="/confirmed" 
        hx-trigger='confirmed'
        onClick="Swal.fire({title: 'Confirm', text:'Do you want to continue?'}).then((result)=>{
            if(result.isConfirmed){
              htmx.trigger(this, 'confirmed');  
            } 
        })">
  Click Me
</button>

在这里,我们使用 JavaScript 在点击时显示 Sweet Alert 2,请求确认。如果用户确认对话框,我们通过触发自定义的 “confirmed” 事件来触发请求,该事件随后被 hx-trigger 捕获。

Vanilla JS,hx-confirm

<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
  document.addEventListener("htmx:confirm", function(e) {
    // The event is triggered on every trigger for a request, so we need to check if the element
    // that triggered the request has a confirm question set via the hx-confirm attribute,
    // if not we can return early and let the default behavior happen
    if (!e.detail.question) return

    // This will prevent the request from being issued to later manually issue it
    e.preventDefault()

    Swal.fire({
      title: "Proceed?",
      text: `I ask you... ${e.detail.question}`
    }).then(function(result) {
      if (result.isConfirmed) {
        // If the user confirms, we manually issue the request
        e.detail.issueRequest(true); // true to skip the built-in window.confirm()
      }
    })
  })
</script>
  
<button hx-get="/confirmed" hx-confirm="Some confirm text here">
  Click Me
</button>

我们添加一些 JavaScript 在点击时调用 Sweet Alert 2,请求确认。如果用户确认对话框,我们通过调用 issueRequest 方法来触发请求。我们将 skipConfirmation=true 作为参数传递,以跳过 window.confirm

这允许在提示中使用 hx-confirm 的值,这在问题取决于元素时很方便,例如 Django 列表:

{% for client in clients %}
<button hx-post="/delete/{{client.pk}}" hx-confirm="Delete {{client.name}}??">Delete</button>
{% endfor %}

了解更多关于 htmx:confirm 事件的信息,请参阅 此处