【Spring Boot】ThymeleafでJavaScriptに値を渡す方法

Thymeleafを用いてページを作成していた際に、htmlのように単純式等を使用してJavaScriptに値を渡したい場面があったため、今回その方法についてまとめました。

方法

結論から言うと、Thymeleafの独自属性であるth:inlineを使うことでJavaScriptの処理に値を渡すことができます。

th:inlineとはその名の通りインライン処理用の属性で、htmlにJavaScriptの処理を直接埋め込みたいとき等に使用します。

ではその使い方を見ていきましょう。

th:inlineの使い方

基本

インライン処理を行いたい要素にth:inlineの値を設定します。
設定できる値は“text”“javascript”“none”の3種類です。

この属性を持たせることでその要素と子要素以下ではThymeleafのインライン処理が有効になります。

またThymeleafの単純式等、通常の文字列以外として認識させたい場合は[[…]]で囲みます。

HTML(インライン処理の有無確認)
<!--/* そのまま文字列として画面に表示される */-->
<div th:inline="text">
  ${username}
</div>
<!--/* 変数の値が画面に表示される(username="taro") */-->
<div th:inline="text">
  [[${username}]]
</div>

○ブラウザ(Thymeleafのインライン処理あり)

また[[…]]はThymeleafのインライン処理が有効になっていない場合に文字列として処理されてしまうため、直接開いてしまうとそのまま表示されてしまいます。

○ブラウザ(直接開いた場合)

そのためプロトタイプとしても使用したい場合は、コメントアウトする必要があります。

直接開いた際にコメントアウトしたい部分は<!—/*/と/*/—>で挟み込み、逆にThymeleafを介したときにコメントアウトしたい部分は<!—/* —><!— */—>で挟み込みましょう。

HTML(コメントアウト)
<!-- Thymeleafを介した場合に画面に表示される(username="taro") -->
<!--/*/
<div th:inline="text">
  [[${username}]]
</div>
/*/-->
<!--/*/ 直接開いた場合に画面に表示される /*/-->
<!--/* -->
<div>テストユーザ</div>
<!-- */-->

○ブラウザ(Thymeleafのインライン処理あり)

○ブラウザ(直接開いた場合)

JavaScriptのインライン処理

上記を踏まえたうえで、本題のJavaScriptへの値渡しを解説していきます。

ThymeleafではJavaScriptを埋め込む場合、通常のhtmlと同じようにscriptタグを用意し、さらにth:inlineを持たせてjavascriptと設定します。

HTML(JavaScriptを埋め込む際のth:inline)
<script th:inline="javascript">
  ...
</script>

そのあとは基本通り[[…]]の中に単純式などを記載すれば値を渡すことができます。

HTML(単純式を追加)
<script th:inline="javascript">
  var username = [[${username}]]
  ...
</script>

ここでは文字列を渡していますが、ほかにも下記オブジェクトを渡すことが可能です。

  • 数値
  • 真偽値
  • 配列
  • コレクション
  • マップ
  • Beans

ただし上の記述の場合、エディタ上ではエラー扱いとなってしまいます。また直接開く場合もエラーとなり、想定通りに動かなくなってしまいます。

○エディタ

ブラウザ(開発者ツール)

そのため、基本と同じようにThymeleaf独自の記述はコメントアウトし、エディタや直接開く際のブラウザにはコメントとして認識してもらいます。

JavaScriptのコメントアウトは/*…*/を使用します。先程エラーとなっていた部分をコメントアウトしてみましょう。

HTML(Thymeleaf用の記述をコメントアウト)
<script th:inline="javascript">
  var username = /*[[${username}]]*/
</script>

すると先程のエラーは解消されますが、式が不完全になり別のエラーが発生します。これはコメントアウトしたことにより代入する値がなくなってしまったからです。

ブラウザ(開発者ツール)

したがって、コメントアウトされたときに代わりに入力する値をその後ろに記載しておきましょう。

HTML(Thymeleafのインライン処理無効時の値を記述)
<script th:inline="javascript">
  var username = /*[[${username}]]*/ "テストユーザ";
  ...
</script>

これでJavaScriptの処理に値を渡すことができ、直接開いた場合でも正常に動くようになりました。

では、次に実際の実装例を確認してみましょう。

実際の実装例

今回はformタグ内のテキストボックスにあらかじめ値が入っているような画面を作成してみます。

単純式で値を渡す

Java(Get/PutMappingとUserInfoクラス)
@GetMapping("")
public String index(Model model) {
	model.addAttribute("username", "taro");
	return "index";

@PostMapping("")
public String index(Model model, UserInfo userInfo) {
  model.addAttribute("username", "taro");
  return "index";

public class UserInfo {
  private String name;
  
  public void setName(String name) {
		this.name = name;
	}
	
	public String getName() {
		return this.name;
	}
}
HTML(単純式で値を渡す)
<form th:action="@{/index}" th:object="${userInfo}" method="post" accept-charset="UTF-8">
	<input type="text" id="name" th:field="*{name}">
	<input type="submit" value="送信">
</form>
<div th:text="${userInfo.name}">未入力</div>
<script th:inline="javascript">
	var input = document.getElementById("name");
	input.value = /*[[${username}]]*/ "";
</script>

上記は送信ボタン押下でテキストボックス内の文字列が表示される画面となっています。(直接開いた場合はテキストボックスの内容に関係なく”未入力”と表示される。)

またテキストボックスはサーバから受け取った“taro”で初期化されるようになっています。

○ブラウザ(Thymeleafのインライン処理ありの初期表示)

テキストボックスのidには“name”を設定していますが、th:objectを使用しているためThymeleafを介すと指定したオブジェクトのフィールド名にidが書き換えられてしまうことに注意しましょう。(th:objectの詳細は「【Spring Boot】Thymeleafの選択変数式 html編」で説明しています)

試しに2行目と7行目のidを”name”以外に変更するとテキストボックスが初期化されないことが確認できると思います。

上書きされるため不要ですが、今回は直接開かれることを考慮してidを記載しています。(直接開いた場合、idの書き換えが発生しないためにid=”name”をもつ要素が存在せず、JavaScriptの要素取得に失敗する)

コードの追加

前項ではインライン処理の有効/無効に応じて初期表示する値を変更していましたが、よく見てみると直接開いた場合は空文字を渡しているため処理自体不要なことがわかります。

このようにインライン処理が有効な場合のみ動かしたい処理があるときはコードの追加を行うのも一つの手です。

ThymeleafではJavaScriptのインライン処理が有効である場合でのみ、/*[+/と+]*/で囲まれた部分の処理が有効になります。そのため前項の処理は下記のように書き換えられます。

HTML(コードの追加)
<form th:action="@{/index}" th:object="${userInfo}" method="post" accept-charset="UTF-8">
	<input type="text" th:field="*{name}">
	<input type="submit" value="送信">
</form>
<div th:text="${userInfo.name}">未入力</div>
<script th:inline="javascript">
  /*[+
	var input = document.getElementById("name");
	input.value = [[${username}]];
	+]*/
</script>

まとめ

Thymeleafを用いてJavaScriptに値を渡す場合は独自属性のth:inlineを使用する。使用方法は下記の通り。

  1. scriptタグにth:inline=”javascript”を設定(インライン処理の有効化)
  2. /*[[…]]*/で単純式などの記述を囲む
  3. 2.の後ろにインライン処理無効時の値を記述

インライン処理が有効な場合のみJavaScriptの一部処理を有効化したい際には、該当する処理を/*[+/と+]*/で囲む。

コメント

タイトルとURLをコピーしました