编辑行

此示例展示了如何实现可编辑行。首先让我们看一下表体:

¥This example shows how to implement editable rows. First let’s look at the table body:



<table class="table delete-row-example">
  <thead>
    <tr>
      <th>名称</th>
      <th>电子邮件</th> 
      <th></th>
    </tr>
  </thead>
  <tbody hx-target="closest tr" hx-swap="outerHTML">
    ...
  </tbody>
</table>


这将告诉表格内的请求以触发请求的最近封闭行为目标并替换整行。

¥This will tell the requests from within the table to target the closest enclosing row that the request is triggered on and to replace the entire row.

以下是行的 HTML:

¥Here is the HTML for a row:

<tr>
      <td>${contact.name}</td>
      <td>${contact.email}</td>
      <td>
        <button class="btn danger"
                hx-get="/contact/${contact.id}/edit"
                hx-trigger="edit"
                onClick="let editing = document.querySelector('.editing')
                         if(editing) {
                           Swal.fire({title: 'Already Editing',
                                      showCancelButton: true,
                                      confirmButtonText: 'Yep, Edit This Row!',
                                      text:'Hey!  You are already editing a row!  Do you want to cancel that edit and continue?'})
                           .then((result) => {
                                if(result.isConfirmed) {
                                   htmx.trigger(editing, 'cancel')
                                   htmx.trigger(this, 'edit')
                                }
                            })
                         } else {
                            htmx.trigger(this, 'edit')
                         }">
          Edit
        </button>
      </td>
    </tr>

在这里,我们变得有点花哨,只允许一次编辑一行,使用一些 JavaScript。我们检查是否有一行带有 .editing 类,并确认用户想要编辑此行并忽略另一行。如果是这样,我们会向另一行发送一个取消事件,以便它将发出返回其初始状态的请求。

¥Here we are getting a bit fancy and only allowing one row at a time to be edited, using some JavaScript. We check to see if there is a row with the .editing class on it and confirm that the user wants to edit this row and dismiss the other one. If so, we send a cancel event to the other row so it will issue a request to go back to its initial state.

然后我们在当前元素上触发 edit 事件,该事件触发 htmx 请求以获取行的可编辑版本。

¥We then trigger the edit event on the current element, which triggers the htmx request to get the editable version of the row.

请注意,如果你不关心用户是否编辑多行,则可以省略超标和自定义 hx-trigger,只让正常的点击处理与 htmx 一起工作。你还可以通过在单击“编辑”按钮时简单地定位整个表来实现互斥性。在这里,我们想展示如何集成 htmx 和 JavaScript 来解决问题并稍微缩小服务器交互范围,此外我们还可以使用一个不错的 SweetAlert 确认对话框。

¥Note that if you didn’t care if a user was editing multiple rows, you could omit the hyperscript and custom hx-trigger, and just let the normal click handling work with htmx. You could also implement mutual exclusivity by simply targeting the entire table when the Edit button was clicked. Here we wanted to show how to integrate htmx and JavaScript to solve the problem and narrow down the server interactions a bit, plus we get to use a nice SweetAlert confirm dialog.

最后,这是编辑数据时行的样子:

¥Finally, here is what the row looks like when the data is being edited:

<tr hx-trigger='cancel' class='editing' hx-get="/contact/${contact.id}">
  <td><input autofocus name='name' value='${contact.name}'></td>
  <td><input name='email' value='${contact.email}'></td>
  <td>
    <button class="btn danger" hx-get="/contact/${contact.id}">
      Cancel
    </button>
    <button class="btn danger" hx-put="/contact/${contact.id}" hx-include="closest tr">
      Save
    </button>
  </td>
</tr>

这里我们做了一些事情:首先,行本身可以响应 cancel 事件,这将带回行的只读版本。有一个取消按钮,可以取消当前编辑。最后,有一个保存按钮发出 PUT 来更新联系人。请注意,在最近的行中有一个包含所有输入的 hx-include。由于 HTML 限制(不能将 form 直接放在 tr 内),表格行在表单中使用起来非常困难,因此这会让事情变得更容易处理。

¥Here we have a few things going on: First off the row itself can respond to the cancel event, which will bring back the read-only version of the row. There is a cancel button that allows cancelling the current edit. Finally, there is a save button that issues a PUT to update the contact. Note that there is an hx-include that includes all the inputs in the closest row. Tables rows are notoriously difficult to use with forms due to HTML constraints (you can’t put a form directly inside a tr) so this makes things a bit nicer to deal with.

Server Requests ↑ Show

🔗Demo