htmxを使ってみた-(1)htmxの基本-

## htmxとは何か
* [htmx](https://htmx.org/)とは、HTMLのタグに独自の属性(attribute)を付けることで、簡単にAJAXできるようにするJavaScriptライブラリ（小さなフレームワーク）です。
* HTMLの自然な拡張になっており、JacaScriptのコードをほとんど書く必要がありません。
* サーバーからの応答はHTML形式を想定しています。
* 最近流行ののSPA（Single Page Application)を作るのに適しています。
* 学習コストが低く、他のライブラリのように、独自の文法や使い方を覚える必要がありません。
* jQueryの代替になるかもしれません。

以下、[htmxのドキュメントの抜粋](https://htmx.org/docs/)＝私が理解して使ったものだけ＝です。

## htmxのインストール
[UNPKGの当該ページからダウンロード](https://unpkg.com/browse/htmx.org@2.0.2/)して、scriptタグで貼り付けます。
2020/10/10現在の最新バージョンは、2.0.2でした。
ダウンロードしたファイルには、バージョン番号を付けておくことを推奨します。
HTMLファイルのヘッダに、
```HTML
<script src="htmx-2.0.2.js"></script>
```
などとして貼り付けます。

## htmxの基本
htmxはHTMLのタグに独自の属性を付けることで、AJAXができるようにしています。
例えば、
```HTML
<div hx-get="/get_message">Click</div>
```
のように記述すると、
1. DIVタグをクリックすることで、（デフォルトのAJAXのトリガはクリック）
1. hx-get属性により、HTTPのGETメソッドで、サーバーの /get_message にアクセスし、
1. サーバーからの返答(HTMLデータ）で、DIVタグの中身を入れ替える。（デフォルトで、入れ替える先は自分自身の中身）

という動作をします。
他のライブラリやフレームワークに比べて、簡単にAJAXを実現することができます。

## サポートするHTTPメソッド
htmxがサポートするHTTPメソッドは以下のとおりです。
| htmx属性 | HTTPメソッド | 説明 |
|:-|:-|:-|
| hx-get  | GET  | 参照：データを要求する  |
| hx-post  | POST  | 新規作成：新しいデータの作成を要求する  |
| hx-put  | PUT  | 更新：データを更新する  |
| hx-patch  | PATCH  | 一部更新：データの一部を更新する  |
| hx-delete  | DELETE  | 削除：データの削除を要求する  |

## AJAXのトリガー
AJAXリクエストが行われるためのトリガーは以下のとおりです。
| HTMLタグ | トリガー |
|:-|:-|
| input、textarea、select | 内容が変わったとき(onChange)  |
| form | submitされたとき(submitボタンが押された)(onSubmit)  |
| その他  | クリックされたとき(onClick)  |

発火を遅らせる、ポーリング、特定のキーの組み合わせ、特別なイベントなど、トリガーを修飾することができます。

## AJAXの適用先
標準では、自分自身ですが、hx-target属性で、適用先（書き換え先）を指定することができます。
```HTML
<button hx-get="/example" hx-target="#search-results">Get Some HTML</button>
<div id="search-results"></div>
```

適用先の指定には、CSSセレクタが使えます。
上記の例では、
1. ボタンをクリックすると、
1. hx-get属性により、HTTPのGETメソッドで、サーバーの/exampleにアクセスし、
1. hx-target属性により、サーバーからの応答で、idに"search-results"を持つタグの中身を書き換えます。

## 要素の置換方法
標準ではタグの中身を書き換えますが、hx-swap属性で、置換方法を指定することができます。
| 指定方法 | 置換方法 |
|:-|:-|
| innerHTML  | 要素の中身。 **標準**  |
| outerHTML  | 要素そのもの＝タグとその中身を書き換える  |
| afterbegin  | 要素内の最初の子要素の前に追加します  |
| beforebegin  | 要素の直前に追加  |
| beforeend  | 要素内の最後の子要素の後に追加します  |
| afterend  | 要素の直後に追加  |
| delete  | 要素を削除  |
| none  | 何もしない  |

置換をモーフィングさせることや、オプションで置換の様子を変えることもできます。

## 「boost」対応
アンカータグ（\<a\>）やフォームタグ（\<form\>）は、サーバーからのページ全体のデーターを送ってもらいブラウザを書き換え（ページ遷移）ますが、htmxでは、hx-boost属性を設定することで、アンカータグやフォームタグをAJAX化して、\<body\>の内容だけを書き換えるようにできます。
```HTML
<div hx-boost="true">
    <a href="/blog">Blog</a>
</div>
```

HTMLの\<head\>で多くのファイルを読み込ませている場合に便利だそうです。

## イベント対応
hx-on属性を付けることで、要素にイベントをつけることができます。
主な（使用頻度の高そうな）イベントには次のものがあります。
| イベント名 | 説明 |
|:-|:-|
| afterRequest  | AJAXが完了した  |
| afterSettle  | DOMが落ち着いた  |
| afterSwap  | 要素が書き換えられた  |
| beforeRequest  | AJAXを実行する前  |
| beforeSwap  | 要素を書き換える前  |
| beforeSend  | AJAXリクエストを送る前  |
| responseError  | HTTPレスポンスがエラーコード(200 または 300 代以外)を返したとき |
| sendError  | ネットワークエラーによりHTTPリクエストができない  |
| swapError  | 要素の書き換え時にエラーが起こった  |
| targetError  | 無効なターゲットが指定された  |
| timeout  | リクエストがタイムアウトした  |

他にも[多くのイベント](https://htmx.org/reference/#events)があります。
イベントを使う場合は、
```HTML
<button hx-get="/info" hx-on::before-request="alert('Making a request!')">
    Get Info!
</button>
```
のように記述します。
イベント名はキャメルケースで書かれていますが、**HTMLに記述するときはケバブケース**にする必要があります。(ver.2.0.2の制限か？）

## JavaScript API
htmxには、簡単にJavaScriptを呼び出す仕組みがあります。
主な（使用頻度の高そうな）ものには次のものがあります。
| JavaScript API | 説明 |
|:-|:-|
| htmx.addClass()  | 要素にCSSのクラスを追加  |
| htmx.closest()  | 親要素のセレクタに合うもので一番近いものを選択  |
| htmx.find()  | セレクタに合う要素を選択  |
| htmx.findAll()  | セレクタに合う要素をすべて選択  |
| htmx.remove()  | 要素を削除  |
| htmx.removeClass()  | 要素からCSSクラスを削除  |
| htmx.toggleClass()  | 要素のクラスを入れ替える  |
| htmx.values()  | 要素の値を得る  |

他にも、[多くのAPI](https://htmx.org/reference/#api)があります。
APIを使う場合は、
```JavaScript
var div = htmx.find("#my-div")
```

```JavaScript
htmx.addClass(htmx.find('#demo'), 'myClass');
```

のように記述します。

## 関連記事一覧
[htmxを使ってみた-(1)htmxの基本-](https://qiita.com/Final1900/items/49a8ac6f27a2427f6306)
[htmxを使ってみた-(2)準備-](https://qiita.com/Final1900/items/9e46fd6630e4bdf90a73)
[htmxを使ってみた-(3)ルート関数-](https://qiita.com/Final1900/items/293a0c8b42465bbb5142)
[htmxを使ってみた-(4)htmxを使う-](https://qiita.com/Final1900/items/f745c4cc34c8d36548f7)
[htmxを使ってみた-(5)HTMLのdialog-](https://qiita.com/Final1900/items/8584ead01e9c842cc60f)
[htmxを使ってみた-(6)データの表示-](https://qiita.com/Final1900/items/33df506cbeb5979c3cfc)
[htmxを使ってみた-(7)データ追加-](https://qiita.com/Final1900/items/a8206948e6d9ac98f105)
[htmxを使ってみた-(8)要素の変更-](https://qiita.com/Final1900/items/aefc518dacbfaf5d9a2a)
[htmxを使ってみた-(9)ページの再読み込み-](https://qiita.com/Final1900/items/783284ff1ad1d02810d5)
[htmxを使ってみた-(10)データの変更-](https://qiita.com/Final1900/items/9541c05d392b137266f3)
[htmxを使ってみた-(11)データベースの排他制御-](https://qiita.com/Final1900/items/db2a48748cd45262ac8b)
[htmxを使ってみた-(12)確認ダイアローグ-](https://qiita.com/Final1900/items/08e1fb3608d3cf0cbc8c)
[htmxを使ってみた-(13)データ削除-(最終)](https://qiita.com/Final1900/items/5389a4890e0d08549810)