🕌

【Spring Boot入門】 Spring Boot × Thymeleafでカテゴリ絞り込みUIを実装してみた話

に公開

前回、スキルを登録&一覧表示できるWebアプリをSpring Bootで作成しました。
今回は、より使いやすくするために「カテゴリでの絞り込み」+「UI改善(Bootstrap)」にチャレンジしてみました。


✅ やりたかったこと

  • カテゴリ名をクリックすると、そのカテゴリのスキルログだけを表示
  • 絞り込み中のカテゴリが明示される
  • 選択中のカテゴリボタンを Bootstrap の active クラスで強調し、ユーザーが現在の絞り込み状態を視覚的に把握できるようにする

list
list2
list3


💻 実装内容

🔸 Controllerの修正

Controllerでは、カテゴリIDをもとにスキルログを取得し、ビューでの表示切り替えに必要なデータをModelに詰めています。なお、selectedCategory が null のとき(=「すべて」選択時)は全件表示されるような制御も別途Controller側で可能です。
この listByCategory() メソッドでは、以下の3つの情報を Model に詰めています:

  • skillLogs:選択されたカテゴリに紐づくスキルログの一覧(SkillLogエンティティのリスト)
  • categories:カテゴリ一覧を格納したリスト(Categoryエンティティの全件)
  • selectedCategory:現在選択されているカテゴリ(Categoryエンティティ)。画面側でハイライトや表示切り替えに使用

※いずれもSpring Bootで定義したエンティティクラスで、Modelに渡すことでThymeleaf側で直接扱えるようになります。

本番環境では、IDが存在しない場合に orElseThrow() を使って404処理を入れても良いかもしれません。

・SkillLogWebController.java

@GetMapping("/category/{id}")
public String listByCategory(@PathVariable Long id, Model model) {
    List<SkillLog> filteredLogs = skillLogService.findByCategoryId(id);
    Category selectedCategory = categoryService.findById(id).orElse(null);

    model.addAttribute("skillLogs", filteredLogs);
    model.addAttribute("categories", categoryService.findAll());
    model.addAttribute("selectedCategory", selectedCategory);
    return "skilllog/list";
}

🔸 HTML(Thymleafテンプレート)の更新

①「すべて」ボタンとカテゴリごとのリンクを表示

th:each="category : ${categories}" により、Modelから渡されたカテゴリリストをループ処理して、カテゴリごとのリンクボタンを表示しています。

th:classappendにより、選択されたカテゴリのボタンにのみ active クラスを動的に付加しています。ボタンの見た目が変化することで、現在のフィルタ状態が一目でわかります。

Bootstrap の btn-outline-primary は未選択時の基本デザインであり、active が付与された際には色味が変わって強調されます(例:背景色が青系になる)。この差異により、どのカテゴリが現在選択されているかが直感的に把握できるようになります。

・list.html

<h5>カテゴリで絞り込み</h5>
<div class="mb-3">
  <a th:href="@{/skilllog-web}" 
     class="btn btn-outline-secondary btn-sm me-2"
     th:classappend="${selectedCategory == null} ? ' active' : ''">すべて</a>
  <span th:each="category : ${categories}">
    <a th:href="@{'/skilllog-web/category/' + ${category.id}}"
       th:text="${category.name}"
       class="btn btn-outline-primary btn-sm me-2"
       th:classappend="${selectedCategory != null and selectedCategory.id == category.id} ? ' active' : ''"></a>
  </span>
</div>

② 現在の絞り込み状態を明示

selectedCategory が null でなければ、「今表示しているカテゴリ名」を画面に表示
条件分岐は th:if で簡単に実装可能
画面の冒頭に「状態の見える化」を入れるだけで UX がぐっと向上しました

<div th:if="${selectedCategory != null}" class="mb-2">
  <strong th:text="'『' + ${selectedCategory.name} + '』カテゴリのログを表示中'"></strong>
</div>

🧠 学び・気づき

th:classappendを使えば、を活用すれば、UIの状態管理をHTMLテンプレート側で完結できて便利
・画面上部に「現在の状態」を明示するだけで、UXがぐっと上がる
・ThymeleafはJava側のModelデータをそのまま扱えるため、フロント実装の学習コストが低い

✏️ まとめ

今回はカテゴリごとの絞り込みUIを追加しました。
今後は、カテゴリの追加・編集・削除といった管理機能にも挑戦して、さらに実用的なアプリに育てていけたらと思います!

Discussion