質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Thymeleaf

Thymeleaf(タイムリーフ)とは、Java用のテンプレートエンジンで、特定のフレームワークに依存せず使用することが可能です。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

1回答

232閲覧

th:insertに変数を代入したい

trt2020xzn

総合スコア3

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Thymeleaf

Thymeleaf(タイムリーフ)とは、Java用のテンプレートエンジンで、特定のフレームワークに依存せず使用することが可能です。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

0クリップ

投稿2024/03/02 06:12

編集2024/03/02 06:12

thymeleafの初心者です。
A.htmlの中にB.htmlのbodyをインクルードしたいです。
B.htmlは素のhtmlじゃなきゃいけないので、fragmentは使えません。

<div th:insert="../static/html/B.html::body">

直接B.htmlと書く場合はうまく行きますが、
例えばサーバ側(Model)からhtmlFilenameという変数が渡されて、
それをB.htmlの部分に置き換えたい場合は、
どう書けば良いでしょうか。

<div th:insert="../static/html/${htmlFilename}::body">

ではうまく行きませんでした。

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2024/03/02 07:27

>B.htmlは素のhtmlじゃなきゃいけないので それはなぜ・どういう意味でしょうか。 fragment の定義が入っていても html としては問題無いと思いますが。
trt2020xzn

2024/03/02 07:55 編集

コメントありがとうございます。 B.htmlは他者からいただく予定のファイルで、できればいじりたくありません。 B.htmlの中にthymeleafに関する要素(fragment)を入れたくないという意味です。
jimbe

2024/03/02 08:28

>B.htmlは他者からいただく予定のファイル なるほど、ありがとうございます。
guest

回答1

0

ベストアンサー

とりあえず、Thymeleaf 単体で動かして見ます。
参考: Thymeleafテンプレートエンジンをそれ単体で使う
Thymeleaf : thymeleaf-3.1.1.RELEASE (今の最新は 3.1.2 みたいですがたまたまテスト環境に入ってたのでそのまま)

java

1import java.io.FileWriter; 2import java.io.Writer; 3 4import org.thymeleaf.TemplateEngine; 5import org.thymeleaf.context.Context; 6import org.thymeleaf.context.IContext; 7import org.thymeleaf.templateresolver.FileTemplateResolver; 8 9public class Main { 10 public static void main(String[] args) throws Exception { 11 TemplateEngine engine = initializeTemplateEngine(); 12 IContext context = makeContext("B.html", "foo", "bar", "baz"); 13 try(Writer writer = new FileWriter("output.html")) { 14 engine.process("input", context, writer); 15 } 16 } 17 18 private static TemplateEngine initializeTemplateEngine() { 19 TemplateEngine templateEngine = new TemplateEngine(); 20 FileTemplateResolver resolver = new FileTemplateResolver(); 21 resolver.setTemplateMode("XHTML"); 22 resolver.setPrefix(""); 23 resolver.setSuffix(".html"); 24 templateEngine.setTemplateResolver(resolver); 25 return templateEngine; 26 } 27 28 private static IContext makeContext(String htmlFilename, String... args) { 29 Context context = new Context(); 30 context.setVariable("htmlFilename", htmlFilename); 31 context.setVariable("args", args); 32 return context; 33 } 34}

input.html

html

1<?xml version="1.0" encoding="utf-8"?> 2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3<html xmlns="http://www.w3.org/1999/xhtml" 4 xmlns:th="http://www.thymeleaf.org" xml:lang="ja" lang="ja"> 5<head> 6<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 7<title>Sample</title> 8</head> 9<body th:replace="${htmlFilename}::body"> 10 <h1>Arguments</h1> 11 <p> 12 The sample application received 13 <span th:text="${#arrays.isEmpty(args)} ? 'no' : 'some'">...</span> 14 arguments. 15 </p> 16 <ul> 17 <li th:each="a : ${args}"><span th:text="${a}">...</span></li> 18 </ul> 19</body> 20</html>

B.html

html

1<?xml version="1.0" encoding="utf-8"?> 2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xml:lang="ja" lang="ja"> 4<head> 5<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 6<title>B</title> 7</head> 8<body> 9 <p>BBBBBBBBBBBBB</p> 10</body> 11</html>

実行結果 output.html

html

1<?xml version="1.0" encoding="utf-8"?> 2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3<html xmlns="http://www.w3.org/1999/xhtml" 4 xml:lang="ja" lang="ja"> 5<head> 6<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 7<title>Sample</title> 8</head> 9<body> 10 <p>BBBBBBBBBBBBB</p> 11</body> 12</html>

insert でなく replace ですが、変数でファイル名を指定出来ています。

<div th:insert="../static/html/${htmlFilename}::body"> ではうまく行きませんでした。

というのが具体的どういう結果だったのか(何かエラーなのか空白なのかそれとも何か…)分かりませんが、少なくとも動的には出来るようですので、パスも変数に含ませてみるとか、パスを html に書かないといけないならパラメータ全体をリテラル置換で編集してみるとかで何とかなりそうな気がします。

投稿2024/03/02 08:35

編集2024/03/03 07:40
jimbe

総合スコア12648

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

trt2020xzn

2024/03/02 08:50

ありがとうございます。 試してみますが、思っていたのとちょっと違いますね。 以下のような形で変数を渡そうとしていました。 @GetMapping("xxx") public String xxx(Model model) { model.addAttribute("htmlFilename", "B.html"); return "A.html"; }
jimbe

2024/03/02 09:39 編集

Spring での書き方とは違いますのでそのまま回答のコードを Spring に持って行くことは出来ません。 が、内部で Thymeleaf が動作していて値がエンジンに渡されて処理が行われているという点では同じです。 渡し方が回答では Context で、 Spring では model というだけです。 もし model に設定した htmlFilename がテンプレートで参照できないとかなら Spring の問題ですが、値は渡っているのに insert されないということなら Thymeleaf でのことですので、そこを切り分けないと問題を大きく考え過ぎてしまいます。 回答の java コードは Spring が内部で行っていることを模したものです。 テンプレート(html) は、 B.html はそのまま、 input.html が A.html に該当し、結果として生成された output.html は Spring がクライアントに返すモノに当たります。 もし完全に trt2020xzn さんの環境から再現しようとすると質問で書いて頂いている情報だけでは足りません。 一般的には問題の発生するなるべく小さい環境を再現してそれでテスト・修正をし、解決したらその *方法* を本番に反映するという流れで、本番環境の複雑さの影響を受けずに調査を進めます。その為に teratail help でも「3-5. あなたが何をしたかを書きましょう」(https://teratail.com/help/question-tips#questionTips35) のアドバイスとして >関連するソースコードを抽出して本文に含めましょう。 多すぎず、少なすぎずという分量の判断は難しいことですが、読むのに苦痛ではないくらいの量に抑える必要があり、でも問題の本質がわかるほどには多くなければいけません。最も良いのは、 *現象を再現するためのミニマムなプログラムを改めて作ることです。* そうすれば、貴方自身が現象と問題をより良く理解することにもつながるからです。 と書いています。 私は問題の本質は "th:insert に変数を書いて動的に変えることが出来るか" という事と理解しましたので、( ths:replace ですが) ミニマムなプログラムとして回答のコードを作りました。結果として変数を指定して処理が行われましたので、後はパスを含む形としてどうするかだけだと考えています。
trt2020xzn

2024/03/02 11:08

アドバイスありがとうございます。 >もし model に設定した htmlFilename がテンプレートで参照できないとかなら Spring の問題ですが、値は渡っているのに insert されないということなら Thymeleaf でのことですので、そこを切り分けないと問題を大きく考え過ぎてしまいます。 Modelから渡した変数は、html側でth:textで出力できているので、 Springの問題ではないと思います。 ただ、th:insertのパスに含めると、エラーが出てしまいます。 (エラーは確かerror parsingか何か...すみません、今手元にコードがなくて) なので、ただのth:insertの書き方の問題なんじゃないかと疑っていました。 来週また詳しい情報を提供します。
jimbe

2024/03/02 12:02 編集

>なので、ただのth:insertの書き方の問題なんじゃないかと疑っていました。 であれば私と同じ感じですね。 なのでそこだけに違うを注目すると >th:insert="../static/html/${htmlFilename}::body" ではうまくいかないようでも私のほうで >th:replace="${htmlFilename}::body" は出来ています。違いは (insert と replace に違いが無ければ) "../static/html/" があるかないかだけです。 例えば >th:insert="../static/html/${htmlFilename}::body" と >model.addAttribute("htmlFilename", "B.html"); を th:insert="${htmlFilename}::body" と model.addAttribute("htmlFilename", "../static/html/B.html"); にしたら(パスが合っているとすれば)動くかも?と想像しています。 また、回答に書きました通りリテラル置換を使って(model の addAttribute は変えずに) th:insert="|../static/html/${htmlFilename}|::body" というのもありかもしれません。
trt2020xzn

2024/03/06 00:23

すみません、通知がなかったので返事が遅れました。 >th:insert="|../static/html/${htmlFilename}|::body" ありがとうございます! これでうまく行きました。 リテラル置換はこんな風に書くんですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問