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