Edit Row

이 μ˜ˆμ œλŠ” νŽΈμ§‘ κ°€λŠ₯ν•œ ν…Œμ΄λΈ” 행을 κ΅¬ν˜„ν•˜λŠ” 방법을 λ³΄μ—¬μ€λ‹ˆλ‹€. λ¨Όμ € ν…Œμ΄λΈ” 본문을 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€:

<table class="table delete-row-example">
  <thead>
    <tr>
      <th>Name</th>
      <th>Email</th>
      <th></th>
    </tr>
  </thead>
  <tbody hx-target="closest tr" hx-swap="outerHTML">
    ...
  </tbody>
</table>

이 μ½”λ“œλŠ” ν…Œμ΄λΈ” λ‚΄μ—μ„œ λ°œμƒν•˜λŠ” μš”μ²­μ΄ 트리거된 κ°€μž₯ κ°€κΉŒμš΄ 행을 λŒ€μƒμœΌλ‘œ ν•˜μ—¬ ν•΄λ‹Ή ν–‰ 전체λ₯Ό κ΅μ²΄ν•˜λ„λ‘ μ„€μ •ν•©λ‹ˆλ‹€.

λ‹€μŒμ€ 각 행에 λŒ€ν•œ HTML μ½”λ“œμž…λ‹ˆλ‹€:

<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 ν΄λž˜μŠ€κ°€ 적용된 행이 μžˆλŠ”μ§€ ν™•μΈν•œ ν›„, μ‚¬μš©μžκ°€ λ‹€λ₯Έ 행을 νŽΈμ§‘ν• μ§€ μ—¬λΆ€λ₯Ό ν™•μΈν•©λ‹ˆλ‹€. λ§Œμ•½ νŽΈμ§‘μ„ κ³„μ†ν•˜κ³  μ‹Άλ‹€λ©΄, 이전 행에 cancel 이벀트λ₯Ό νŠΈλ¦¬κ±°ν•˜μ—¬ ν•΄λ‹Ή 행이 μ›λž˜ μƒνƒœλ‘œ λŒμ•„κ°€κ²Œ ν•©λ‹ˆλ‹€.

κ·Έ ν›„, ν˜„μž¬ μš”μ†Œμ— edit 이벀트λ₯Ό νŠΈλ¦¬κ±°ν•˜μ—¬ ν–‰μ˜ νŽΈμ§‘ κ°€λŠ₯ν•œ 버전을 κ°€μ Έμ˜€λŠ” htmx μš”μ²­μ„ νŠΈλ¦¬κ±°ν•©λ‹ˆλ‹€.

μ—¬λŸ¬ 행을 λ™μ‹œμ— νŽΈμ§‘ν•˜λŠ” 것이 상관없닀면, JavaScript와 μ»€μŠ€ν…€ hx-triggerλ₯Ό μƒλž΅ν•˜κ³  htmx의 κΈ°λ³Έ 클릭 핸듀링을 μ‚¬μš©ν•΄λ„ λ©λ‹ˆλ‹€. λ˜λŠ”, νŽΈμ§‘ λ²„νŠΌμ„ 클릭할 λ•Œ 전체 ν…Œμ΄λΈ”μ„ λŒ€μƒμœΌλ‘œ ν•˜λŠ” λ°©μ‹μœΌλ‘œ μƒν˜Έ 배타성을 κ΅¬ν˜„ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. μ—¬κΈ°μ„œλŠ” htmx와 JavaScriptλ₯Ό ν†΅ν•©ν•˜μ—¬ 문제λ₯Ό ν•΄κ²°ν•˜κ³  μ„œλ²„μ™€μ˜ μƒν˜Έμž‘μš©μ„ μ΅œμ†Œν™”ν•˜λŠ” 방법을 보여주고 있으며, SweetAlert 확인 λŒ€ν™” μƒμžλ₯Ό μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

λ§ˆμ§€λ§‰μœΌλ‘œ, 데이터가 νŽΈμ§‘ 쀑일 λ•Œμ˜ 행은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

<tr hx-trigger='cancel' class='editing' hx-get="/contact/${contact.id}">
  <td><input 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을 직접 넣을 수 μ—†μœΌλ―€λ‘œ 이λ₯Ό 톡해 μ²˜λ¦¬κ°€ μ’€ 더 μˆ˜μ›”ν•΄μ§‘λ‹ˆλ‹€.

Server Requests ↑ Show

πŸ”—Demo