Reputation: 6297
I'm including a template fragment from the same template file. Section "8.1 Including template fragments - Defining and referencing fragments" of the docs states that:
"::domselector" or "this::domselector" Includes a fragment from the same template.
If I haven't misunderstood, I should be able to reference the fragment as follows: th:include="this :: contentB"
or th:include=":: contentB"
but only making full reference th:include="test-fragment :: contentB"
works for me.
This is the sample code:
HomeController.java
@Controller
class HomeController {
@RequestMapping({ "/", "index", "home" })
String index(Model model) {
return "test";
}
}
test.html
<!DOCTYPE html>
<html>
<head></head>
<body>
<ul th:replace="test-fragment :: contentA" />
</body>
</html>
test-fragment.html
<!DOCTYPE html>
<html>
<head></head>
<body>
<ul th:fragment="contentA">
<li th:each="idx : ${#numbers.sequence(1,4)}" th:switch="${idx}">
<th:block th:case="1"
th:include="test-fragment :: contentB"
th:with="strVar = 'One'"/>
<th:block th:case="2"
th:include="this :: contentB"
th:with="strVar = 'Two'"/>
<th:block th:case="3"
th:include=" :: contentB"
th:with="strVar = 'Three'"/>
<th:block th:case="*"
th:include="/test-fragment :: contentB"
th:with="strVar = 'Other'"/>
</li>
</ul>
<span th:fragment="contentB">
<span th:text="|value: ${strVar}|" />
</span>
</body>
</html>
Output is:
<!DOCTYPE html>
<html>
<head></head>
<body>
<ul>
<li><span>value: One</span></li>
<li></li>
<li></li>
<li><span>value: Other</span></li>
</ul>
</body>
</html>
Case 2 and 3 are missing. What am I doing wrong?
I'm testing using Spring Boot 1.3.2.RELEASE
EDIT:
I've made a small test project to reproduce the issue, it can be found here: https://github.com/t-cst/thymeleaf-springboot-test
EDIT:
After some debug, I find out that when the fragment selector is "this :: contentB"
or " :: contentB"
then the template name is resolved as test
instead of test-framgent
. This is done at:
StandardFragment#extractFragment:189
from thymeleaf-2.1.4.RELEASE:
/* 186 */ String targetTemplateName = getTemplateName();
if (targetTemplateName == null) {
if (context != null && context instanceof Arguments) {
targetTemplateName = ((Arguments)context).getTemplateName();
/* 190 */ } else {
throw new TemplateProcessingException(
"In order to extract fragment from current template (templateName == null), processing context " +
"must be a non-null instance of the Arguments class (but is: " +
(context == null? null : context.getClass().getName()) + ")");
/* 195 */ }
}
But I still don't know why this happens in my test.
EDIT:
I've also asked at thymeleaf forum. Maybe it's a bug. I've opened an issue.
Upvotes: 5
Views: 5186
Reputation: 6297
In case someone ends here with the same issue, this is not possible in thymeleaf 2.1.4.RELEASE
version, but it will be in next version 3.0
A comprehensive explanation can be found at this issue comment.
Upvotes: 3