Reputation: 43
I'm trying to create email templates in both plain text and HTML with Thymeleaf. Because I don't want to duplicate the common parts I want to define these parts separately and insert them into the more specific templates.
It works for HTML, but for plain text variables in the common parts are not replaced:
HTML
common.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div th:fragment="header">
<p>
Hello, [( ${name} )]
</p>
</div>
<div th:fragment="footer">
<p>
Bye.
</p>
</div>
</body>
</html>
specific.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div th:replace="html/common::header"></div>
<p>
<a th:href="${myLink}">[( ${myLink} )]</a>
</p>
<div th:replace="html/common::footer"></div>
</body>
</html>
Plain text
header.txt
Hello ${name}
footer.txt
Bye
specific.txt
[( ~{text/header} )]
[( ${myLink} )]
[( ~{text/footer} )]
Result
It all works well for HTML but for the plain text version the ${name}
variable from the inserted header.txt
template is not replaced:
Hello, [#th:block th:utext="${name}"][/th:block]
http://example.com
Bye.
The HTML result looks correct:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div>
<p>
Hello, name-value
</p>
</div>
<p>
<a href="http://example.com">http://example.com</a>
</p>
<div>
<p>
Bye.
</p>
</div>
</body>
</html>
My questions
Upvotes: 4
Views: 2849
Reputation: 21910
For the plain text issue, you can use the [#th:block]
syntax.
Specifically, instead of using this in your specific.txt
:
[( ~{text/header} )]
you can use this:
[#th:block th:replace="text/header"][/th:block]
Also, in the header.txt
file, instead of using this:
Hello ${name}
you need to use this:
Hello [( ${name} )]
This is expression inlining - which you have already used - and is presented here, for reference.
Some additional examples of the [#th:block]
syntax are presented here.
You might think that the [#th:block]
syntax would now allow us to use fragments, in a similar way to the HTML approach. For example, something like this:
DOES NOT WORK:
[#th:block th:replace="text/common :: header"][/th:block]
together with a common.txt
fragment like this:
ALSO DOES NOT WORK:
[#th:block th:fragment="header"]
Hello, [( ${name} )]
[/th:block]
If you try this, you will get the following error:
java.lang.IllegalArgumentException: Template selectors cannot be specified for a template using a TEXT template mode: template insertion operations must be always performed on whole template files, not fragments
The only other thing I would mention here, if you have not already seen or used it, is parameterized fragments. They can make HTML fragments more flexible and re-usable.
Upvotes: 5