サクッとわかるITトレンドでご紹介した「htmx(Hotwire)」。興味ある!という方も多かったのではないでしょうか。そこで、htmxをさらに深掘り。今回は、htmxではDOMをどのように操作するのか、またその書き方を基礎知識とあわせて解説します。
Hotwire(HTML Over The Wire)と呼ばれる、JavaScriptのプログラムを書くことなくAjaxのような動作を実現する技術があります。このHotwireの動作を手軽に実現できるのが【htmxというライブラリ】です。HTMLファイルの中で読み込むだけで簡単に動きのあるウェブサイトを作ることができます。
htmxとDOMをあわせて学ぶ理由とは?
DOMを操作するときは一般的にJavaScriptを使います。Webブラウザに搭載されているJavaScriptエンジンは、JavaScriptが持つ処理だけでなく、Webブラウザに固有のDOM操作などについてのオブジェクトがあらかじめ用意されています。
そして、このオブジェクトに対する操作をすることで、HTMLの要素を操作できるようになっています。ただし、JavaScriptとDOMの両方を学ぶのは大変なので、本稿ではhtmxでDOMを操作する方法を解説します。
DOMを操作するには、ノードの特定方法や、可能な操作について知っておく必要があるため、以降ではそれらについても詳しく解説します。
HTMLは複数の要素を組み合わせて構成されており、Webページ内の要素間の関係をまとめると以下のような木構造で表現できます。
このように、要素間の関係を木構造で表現すると、Webブラウザで表示されたときの要素間の関係がわかりやすくなります。さらに、プログラムを使って要素を操作し、Webページの中身を動的に書き換えられます。要素の中身を変更したり、新たに要素を追加したり、既存の要素を削除したりすることで、ページの内容をリアルタイムに変化させられるのです。
これを実現するためにWebブラウザが備えるしくみとしてDOM(Document Object Model)があります。DOMでは、HTMLの要素をノードやエレメントと呼び、あるノードの上のノードを親ノード、下のノードを子ノードと呼びます。
ノードに対する処理をプログラムで実装することで、下図のようにWebブラウザ上で入力欄に入力された値をチェックしたり、表に行を追加したり、画像を入れ替えたりといった操作が可能になります。
ノードの特定:hx-target属性
DOMを使ってノードを操作するときは、対象となるノードを特定して選択しなければなりません。このとき、ノードを特定する方法として、JavaScriptには次のような関数が用意されています。
この1番目と4番目は1つのノードだけを得ることができますが、残りはノードのリスト、つまり複数のノードの一覧を得ます。このため、得たリストをループして1つずつ取り出すなどの方法で、それぞれのノードにアクセスします。
htmxでは、こちらの記事でも登場したhx-target属性でCSSセレクタを指定します。また、拡張CSSセレクタ構文が使えるため、これらを組み合わせると上記のような特定ができます。
ノードの追加、更新、削除:hx-swap属性
ノードを特定できれば、そのノードを選択してプログラムから操作できます。たとえば、あるノードに新たな子ノードを作成し、既存のノードの配下に追加できます。また、ノードを他のノードで置き換えたり、そのノードの中身を書き換えたりできます。
もちろん、ノードの属性を変更したり、新しい属性を追加したりすることもできます。DOMからノードを削除することも基本的な操作の一部です。
htmxでノードを追加したり、更新したり、削除したりするには、hx-swapという属性を使います。このときに指定できる値として、以下のようなものがあります。
div要素をクリックしたときに、contents.html の内容がdivタグの後ろに追加されるようにするには、以下のように書きます。
▼ hx_swap で追加する
<div
hx-get="contents.html" hx-swap="afterend">変更前のコンテンツ</div>
また、クリックしたときにレスポンスにかかわらず要素を削除したい場合には、以下のように書きます。
▼ hx_swap で削除する
<div
hx-get="contents.html" hx-swap="delete">削除</div>
デフォルトでは、その要素のinnerHTMLを使うので、要素の中身が置き換えられます。
イベントとトリガー条件の指定:hx-trigger属性
Webページは読み込まれて終わるのではなく、利用者によるWebブラウザの操作に反応して、その内容を動的に変化させたいことがあります。このような利用者の操作によって発生するものをイベントと呼びます。
ボタンであれば、クリックしたときになんらかの処理を実行したいものです。このような実行の起点になるものをトリガーといいます。標準では、それぞれの要素ごとにデフォルトのトリガー条件が決められており、htmxでは指定を省略できます。
これとは異なる条件で動作を設定したいとき、htmxではhx-trigger属性を使って、トリガーの条件を指定します。
たとえば、マウスがその要素の上に入ったときに、「enter.html」というファイルから取得した結果を表示するdiv要素を作るには、以下のように書きます。
▼マウスが入ったときに実行
<div hx-get="enter.html" hx-trigger="mouseenter">
マウスを重ねてください
</div>
■トリガーの修飾子
トリガーは単純なものだけでなく、その動作を変更するための修飾子がいくつも用意されています。たとえば、マウスが入った最初のタイミングだけリクエストしたい場合は、hx-triggerにonceを追加します。
これによって、最初にマウスを重ねたタイミングだけリクエストが送信され、書き換えられたあとはリクエストを送信しなくなります。
▼初回だけマウスが入ったときに実行
<div hx-get="enter.html" hx-trigger="mouseenter once">
マウスを重ねてください
</div>
なお、hx-triggerに指定できるものとして、以下のようなものがあります。
これらの属性を使うと、検索欄にキーワードの一部が入力されたときに候補を表示するなど、便利な機能を容易に実現できます。
たとえば、以下のコードのinputタグでは、キーが押されてから500ミリ秒が経過するとHTTPリクエストを発行し、その結果をresultsというidが設定されているdivタグに挿入します。
<input type="text" name="q"
hx-get="/search"
hx-trigger="keyup changed delay:500ms"
hx-target="#results"
placeholder="検索" >
<div id="results"></div>
<div hx-get="click.html" hx-trigger="click[ctrlKey]"> Control( Ctrl )キーを押しながらクリックしてください 。
</div>
属性の継承:hx-confirm属性
削除ボタンを押したときに、本当に削除してよいか確認するメッセージを表示したいことがあります。このように、リクエストを発行する前に確認メッセージを表示するには、hx-confirmという属性を使います。
下記のように書くと、確認メッセージを表示し、OKを押したときだけリクエストを送信します。
<button
hx-delete="/delete" hx-confirm="削除しますか?">削除</button>
htmxの属性の多くは子要素にも継承されます。つまり、属性を指定した要素だけでなく、子要素にも同じ属性が適用されます。これにより、コードの重複を避けられます。
たとえば、下記では、hx-confirm 属性をそれぞれの要素に指定しています。
<button
hx-delete="/delete" hx-confirm="削除しますか?">削除</button>
<button
hx-put="/update" hx-confirm="更新しますか?">更新</button>
これを下記のように親要素に記述すると、HTMLの記述量を減らせます。
<div hx-confirm="よろしいですか?">
<button hx-delete="/delete">削除</button> <button hx-put="/update">更新</button>
</div>
逆に、継承したくない場合は、hx_confirmにunsetという値を設定します。下記のように書くと、削除と更新のボタンでは確認メッセージが表示されますが、キャンセルボタンを押したときは表示されません。
<div hx-confirm="よろしいですか?">
<button hx-delete="/delete">削除</button> <button hx-put="/update">更新</button> <button hx-confirm="unset" hx-get="/"> キャンセル
</button>
</div>
・・・
いかがでしたか。本格的に学ぼうとするとハードルの高いDOMですが、htmxではJavaScriptなしでも必要な操作ができることがわかりました。
まずは、htmxのようなチャレンジしやすいものからはじめて、Web技術の知識を深めていくのもいいですね。
▼htxmでのHTTPの書き方解説はこちらから