# Tham Khảo Nhanh htmx

*Attributes, triggers, swapping, events, extensions*

> Source: htmx Documentation (htmx.org) · MIT

## Cơ Bản

### Cài Đặt

```
<script src="https://unpkg.com/htmx.org@2"></script>

<!-- Or via npm -->
npm install htmx.org
```

### Cách Hoạt Động

| Command | Description |
|---------|-------------|
| `HTML-driven` | Gọi AJAX từ HTML attributes, không cần JS |
| `Swap content` | Server trả về HTML fragment, htmx hoán đổi vào |
| `Progressive` | Cải thiện HTML chuẩn; giảm dần nhẹ nhàng |
| `REST-friendly` | Hoạt động với bất kỳ framework server-side nào |

## Attributes

### Attributes Request Cốt Lõi

| Command | Description |
|---------|-------------|
| `hx-get="/url"` | Gửi request GET đến URL |
| `hx-post="/url"` | Gửi request POST đến URL |
| `hx-put="/url"` | Gửi request PUT đến URL |
| `hx-patch="/url"` | Gửi request PATCH đến URL |
| `hx-delete="/url"` | Gửi request DELETE đến URL |

### Attributes Hành Vi

| Command | Description |
|---------|-------------|
| `hx-trigger` | Sự kiện kích hoạt request |
| `hx-target` | Phần tử để hoán đổi nội dung vào |
| `hx-swap` | Cách hoán đổi nội dung response |
| `hx-select` | Chọn một phần HTML response |
| `hx-vals` | Thêm giá trị bổ sung vào request |
| `hx-confirm` | Hiển thị hộp thoại xác nhận trước request |
| `hx-disable` | Tắt xử lý htmx trên phần tử |

## Triggers

### Cú Pháp Trigger

```
<!-- Default: natural event (click for buttons) -->
<button hx-get="/data">Load</button>

<!-- Custom trigger event -->
<div hx-get="/news" hx-trigger="every 5s">Feed</div>

<!-- Multiple triggers -->
<input hx-get="/search" hx-trigger="keyup changed delay:300ms" />
```

### Bộ Chỉnh Trigger

| Command | Description |
|---------|-------------|
| `changed` | Chỉ kích hoạt khi giá trị thay đổi |
| `delay:Ns` | Chờ N giây trước khi kích hoạt |
| `throttle:Nms` | Throttle một lần mỗi N ms |
| `once` | Chỉ kích hoạt lần đầu tiên |
| `from:selector` | Lắng nghe trên phần tử khác |
| `every Ns` | Poll mỗi N giây |
| `load` | Kích hoạt khi phần tử tải |
| `revealed` | Kích hoạt khi phần tử cuộn vào tầm nhìn |

## Targets

### Chọn Target

```
<!-- Target another element -->
<button hx-get="/data" hx-target="#result">Load</button>
<div id="result"></div>

<!-- Target closest ancestor -->
<button hx-get="/row" hx-target="closest tr">Update</button>

<!-- Target with CSS selector -->
<button hx-get="/info" hx-target="next .output">Go</button>
```

### Từ Khóa Target

| Command | Description |
|---------|-------------|
| `this` | Chính phần tử đó (mặc định) |
| `closest <sel>` | Tổ tiên gần nhất khớp selector |
| `find <sel>` | Con cháu đầu tiên khớp selector |
| `next <sel>` | Anh em tiếp theo khớp selector |
| `previous <sel>` | Anh em trước đó khớp selector |

## Swapping

### Chiến Lược Swap

| Command | Description |
|---------|-------------|
| `innerHTML` | Thay thế nội dung bên trong (mặc định) |
| `outerHTML` | Thay thế toàn bộ phần tử target |
| `afterbegin` | Chèn vào đầu bên trong target |
| `beforeend` | Thêm vào cuối bên trong target |
| `beforebegin` | Chèn trước target |
| `afterend` | Chèn sau target |
| `delete` | Xóa phần tử target |
| `none` | Không swap, chỉ kích hoạt sự kiện |

### Bộ Chỉnh Swap

```
<!-- Swap with transition delay -->
<div hx-get="/data" hx-swap="innerHTML swap:300ms">

<!-- Settle delay for CSS transitions -->
<div hx-get="/data" hx-swap="innerHTML settle:500ms">

<!-- Scroll to top after swap -->
<div hx-get="/page" hx-swap="innerHTML scroll:top">
```

## Headers

### Request Headers (htmx gửi)

| Command | Description |
|---------|-------------|
| `HX-Request` | Luôn là "true" cho request htmx |
| `HX-Target` | ID của phần tử target |
| `HX-Trigger` | ID của phần tử kích hoạt |
| `HX-Trigger-Name` | Tên của phần tử kích hoạt |
| `HX-Current-URL` | URL hiện tại của trình duyệt |
| `HX-Prompt` | Phản hồi người dùng từ hx-prompt |

### Response Headers (server gửi)

| Command | Description |
|---------|-------------|
| `HX-Redirect` | Redirect phía client đến URL |
| `HX-Refresh` | Tải lại toàn trang nếu là "true" |
| `HX-Retarget` | Ghi đè hx-target bằng CSS selector |
| `HX-Reswap` | Ghi đè chiến lược hx-swap |
| `HX-Trigger` | Kích hoạt sự kiện phía client |
| `HX-Push-Url` | Đẩy URL vào lịch sử trình duyệt |

## Events

### Sự Kiện Vòng Đời

| Command | Description |
|---------|-------------|
| `htmx:configRequest` | Trước request; sửa đổi params/headers |
| `htmx:beforeRequest` | Ngay trước cuộc gọi AJAX |
| `htmx:afterRequest` | Sau khi request hoàn tất |
| `htmx:beforeSwap` | Trước khi nội dung được hoán đổi vào |
| `htmx:afterSwap` | Sau khi nội dung được hoán đổi vào |
| `htmx:afterSettle` | Sau khi DOM ổn định từ swap |
| `htmx:responseError` | Server trả về trạng thái lỗi |

### Lắng Nghe Sự Kiện

```
document.body.addEventListener("htmx:afterSwap", (e) => {
  console.log("Swapped:", e.detail.target);
});

// Cancel a request
document.body.addEventListener("htmx:configRequest", (e) => {
  if (!confirm("Proceed?")) e.preventDefault();
});
```

## Extensions

### Sử Dụng Extensions

```
<script src="https://unpkg.com/htmx-ext-json-enc"></script>

<div hx-ext="json-enc">
  <form hx-post="/api/data">
    <input name="title" />
    <button>Submit as JSON</button>
  </form>
</div>
```

### Extensions Phổ Biến

| Command | Description |
|---------|-------------|
| `json-enc` | Encode body request dạng JSON |
| `loading-states` | Quản lý CSS class trạng thái loading |
| `head-support` | Merge tag <head> từ response |
| `preload` | Preload link khi mousedown/hover |
| `sse` | Hỗ trợ Server-Sent Events |
| `ws` | Hỗ trợ WebSocket |
| `response-targets` | Target khác nhau cho response lỗi |

## Indicators

### Chỉ Báo Loading

```
<button hx-get="/slow" hx-indicator="#spinner">
  Load Data
</button>
<span id="spinner" class="htmx-indicator">Loading...</span>
```

### CSS Indicator

```
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator { display: inline; }
.htmx-request.htmx-indicator { display: inline; }
```

*htmx thêm class htmx-request vào phần tử trong khi request*

### Vô Hiệu Hóa Trong Khi Request

```
<button hx-post="/submit" hx-disabled-elt="this">
  Submit
</button>
```

*hx-disabled-elt thêm thuộc tính disabled trong khi request*

## Mẫu Phổ Biến

### Tìm Kiếm Trực Tiếp

```
<input type="search" name="q"
  hx-get="/search"
  hx-trigger="keyup changed delay:300ms"
  hx-target="#results" />
<div id="results"></div>
```

### Cuộn Vô Hạn

```
<tr hx-get="/rows?page=2"
    hx-trigger="revealed"
    hx-swap="afterend">
  <td>Loading more...</td>
</tr>
```

### Xóa Có Xác Nhận

```
<button hx-delete="/item/42"
        hx-confirm="Delete this item?"
        hx-target="closest .item"
        hx-swap="outerHTML">
  Delete
</button>
```

### Chỉnh Sửa Nội Tuyến

```
<div hx-get="/edit/1" hx-trigger="click"
     hx-swap="outerHTML">
  Click to edit this text
</div>
```
