Recursion is a common technique used to iterate through the Tree object and render it in HTML using ordered or unordered lists.
From JSP you could use a function but scriptlets are not desired as we know. A better practice is to use jsp:include to reload the same JSP page for the children of the current node.
Here is an example that builds a vertical menu keeping the needed separation of concerns in your architecture.
First there is a POJO encapsulating typical menu fields:
import java.util.ArrayList; import java.util.List; public class MenuItem { private String key; private String url; private List<MenuItem> menuItems; private boolean selected; public MenuItem(String key, String url, List<MenuItem> menuItems, boolean selected) { super(); this.key = key; this.url = url; this.menuItems = menuItems; this.selected = selected; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public List<MenuItem> getMenuItems() { return menuItems; } public void setMenuItems(List<MenuItem> menuItems) { this.menuItems = menuItems; } public void addMenuItem(MenuItem menuItem){ if(menuItems == null){ menuItems = new ArrayList<MenuItem>(); } menuItems.add(menuItem); } public boolean isSelected() { return selected; } public void setSelected(boolean selected) { this.selected = selected; } }
In your controller you should then fill the verticalMenu list:
List<MenuItem> verticalMenu = new ArrayList<MenuItem>();
The JSP calls itself:
<%@ include file="/WEB-INF/jsp/includes.jsp" %> <ul> <c:forEach var="menuItem" items="${verticalMenu}"> <c:set var="verticalMenu" value="${menuItem.menuItems}" scope="request"/> <li> <c:choose> <c:when test="${menuItem.selected}"> <a href="#" class="selected"><span><c:out value="${menuItem.key}" escapeXml="true"/></span></a> </c:when> <c:otherwise> <c:choose> <c:when test="${ ! empty menuItem.url }"> <a href="<spring:url value="${menuItem.url}"/>"><span><c:out value="${menuItem.key}" escapeXml="true"/></span></a> </c:when> <c:otherwise> <span><c:out value="${menuItem.key}" escapeXml="true"/></span> </c:otherwise> </c:choose> </c:otherwise> </c:choose> <c:if test="${fn:length(menuItem.menuItems) > 0}"> <jsp:include page="/WEB-INF/jsp/verticalMenu.jsp"/> </c:if> </li> </c:forEach> </ul>
And the CSS makes some adjustments:
#sidebar ul { margin: 0; padding: 0; list-style-type: none; } #sidebar ul ul { margin-left: 10px; } #sidebar li { display: block; margin: 0; padding: 1px 0 0 2px; }
1 comment:
This is amazing. Thanks for sharing this example.
Post a Comment