I am trying to create a recursive fragment in Thymeleaf to produce a left-side menu. Core architecture is Spring Boot, and I am passing in a populated Menu object that has children and such. Code for the Menu looks like:
public class MenuItem {
private String displayLabel;
private String actionUri;
private List<MenuItem> children;
// ...getters/setters/etc...
}
And a Thymeleaf fragment defined like:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Menu</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<div th:fragment="submenu (menu)" th:remove="tag">
<ul th:if="${not #lists.isEmpty(menu.children)}" th:class="${#objects.nullSafe(depth, 1) > 1}? 'children'">
<li th:each="child : ${menu.children}">
<span th:if="${#strings.isEmpty(child.actionUri)}" th:text="${child.displayLabel}">Addons</span>
<a th:if="${not #strings.isEmpty(child.actionUri)}" th:href="${child.actionUri}" th:text="${child.displayLabel}">Link Item</a>
<div th:replace="fragments/submenu :: submenu(menu=${child}, depth=depth+1)" th:remove="tag" />
</li>
</ul>
</div>
</body>
</html>
If I take the depth
code out, everything seems to work fine. But with it I get:
2014-07-30 11:13:00.832 ERROR 45869 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "#objects.nullSafe(depth, 1) > 1" (fragments/submenu:9)] with root cause
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
The purpose of the depth
code is so I can optionally put in a class to track when menu items are children of the parent. Is it possible to either fix the depth counter or to do something else to test if the fragment was ran already? Ultimately I just want a recursive menu with the top ul
having no class and the child ul
s having a class of children
.
Try these changes
1.Use two parameters in fragment as
<div th:fragment="submenu (menu, depth)" >
2.Pass the depth as
<div th:replace="fragments/submenu :: submenu(menu=${child}, depth=${depth+1})" />