1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

HTMXとラジオボタンで、メニュータブを作る

Last updated at Posted at 2024-11-24

作りたいもの

メニューリンクが並んでおり、どれかをクリックすると、その詳細が下に表示されるようなものを作ります。
Bootstrapでいうところの ナビゲーションタブ のようなイメージです。

image.png

環境

  • HTMX ver2.0.3

ディレクトリ構造

通常は、各種サーバサイドのフレームワークとテンプレートエンジンを使われると思いますが、今回は簡易的な説明のため、静的なhtmlファイル(active.html, link1.html, link2.html)を、index.htmlから呼び出します。

.
└── htmx-test/
    ├── index.html
    ├── active.html
    ├── link1.html
    └── link2.html

HTML部分

HTMXのドキュメント を参考に、以下のように書きました。

hx-* は、わたしの使っているエディタでエラーが出たので、data-hx-* になっていますが、やっていることは同じです。

※ なお、HTMXは、headタグで読み込んであります。

htmx-test/index.html
    <section id="nav-tab">
        <nav class="tab-menu">
            <input type="radio" name="menu-item" id="active" value="active" checked
                data-hx-get="./active.html" data-hx-trigger="change" 
                data-hx-swap="innerHTML" data-hx-target="#nav-tab>.tab-content"
            />
            <label for="active">Active</label>
            <input type="radio" name="menu-item" id="link1" value="link1" 
                data-hx-get="./link1.html" data-hx-trigger="change" 
                data-hx-swap="innerHTML" data-hx-target="#nav-tab>.tab-content"
            />
            <label for="link1">Link1</label>
            <input type="radio" name="menu-item" id="link2" value="link2" 
                data-hx-get="./link2.html" data-hx-trigger="change" 
                data-hx-swap="innerHTML" data-hx-target="#nav-tab>.tab-content"      
            />
            <label for="link2">Link2</label>
            <input type="radio" name="menu-item" 
                id="disabled" disabled value="disabled" />
            <label for="disabled">Disabled</label>
        </nav>
        <div class="tab-content">
            <div>This is Active page.</div>
        </div>
    </section>

読み込まれる側のHTMLも作っておきます。

htmx-test/active.html
<div>This is Active page.</div>
htmx-test/link1.html
<div>This is Link 1 page.</div>
htmx-test/link2.html
<div>This is Link 2 page.</div>

ちなみに、たとえば、PHPのSymfony系統には、isXmlHttpRequest()というメソッドがあるようです。

なのでもしかしたら、上記のactive.htmlのようなエンドポイントは不要で、index.htmlにアクセスするとき、

  • 通常のアクセス => HTMLすべてを返却
  • HTMX経由(内部的にはAJAX経由)のアクセス => divタグのフラグメントだけを返却

というような実装も可能なのかなと思っています。

Slim frameworkだと、次のような記事を見つけました。
Slim 4 - HTMX Server-side Integration

CSS部分

HTMXを使えば、HTMLにJavaScript操作用のclassセレクタを使用しなくて済むので、CSSも、見やすく書けます。

#nav-tab{
    margin:0 auto;
    padding:.5rem;
    max-width:30rem;
    min-height:20rem;
    border:solid thin gray;
    border-radius: 8px;
    display:flex;
    flex-direction: column;

    > * {
        margin:0;padding:.5rem;
    }
    nav.tab-menu {
        display:flex;
        gap:.5rem;
        border-bottom: solid thin gray;

        input[type=radio] {
            display:none;
        }
        label {
            margin:0;padding:0 .5rem;
            line-height:1.5rem;
        }
        label:hover {
            color:white;
            background-color:navy;
            border-radius: 8px;
            cursor:pointer;
        }
        input[type=radio]:checked {
            + label {
               font-weight: bold;
            }
            + label:hover {
                color:inherit;
                background-color:inherit;
                cursor:inherit;
            }
        }
        input[type=radio]:disabled {
            + label {
                color:gray;
            }
            + label:hover {
                background-color:inherit;
                cursor:not-allowed;
            }
        }
    }
}

感想

これまでは、.active セレクターのようなものを、JavaScriptで付けたり消したりしていましたが、HTMXと、ラジオボタンを利用することで、手間が減りました。

HTMXは、クライアントサイドで状態を管理しようとすると、一気に難易度が上がってしまうので、極力、サーバーサイドで管理するか、今回のように、inputタグを使うなど、工夫が必要だと思っています。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?