Using The View Tag Library

The following example uses the view:iterate tag to iterate over the menu items instead of the specialized menu:iterate tag. This method requires some experience with Java and makes direct use of the MenuItem class.

First of all three tag libraries are declared:

<%@ page language="java" %>
<%@ taglib uri="http://www.escenic.com/taglib/escenic-menu" prefix="MENU" %>
<%@ taglib uri="http://www.escenic.com/taglib/escenic-util" prefix="UTIL" %>
<%@ taglib uri="http://www.escenic.com/taglib/escenic-view" prefix="VIEW" %>

The menu:use tag is used to retrieve the menu and assign it to the scripting variable menu in the the tag body. This variable is suitable for use with the view tag library, and view:iterate to iterate through its contents. This loop flattens the menu hierarchy to a list of plain links:

<MENU:use id="menu" treeName="main">
  <VIEW:iterate id="menuItem" view="<%= menu %>"
                type="com.escenic.menu.MenuItem">
    <a href="<UTIL:valueof param="menuItem.URL" />">
      <UTIL:valueof param="menuItem.text"> </UTIL:valueof>
    </a>
  </VIEW:iterate>
</MENU:use>

menu:iterate, used in the first example is a specialized iteration tag for menus. It is very simple to use and the menu tag library has specialized tags for rendering different types of menu items. view:iterate, on the other hand, offers full control over the iteration process but is more difficult to use. The view tag library does not have specialized rendering tags, but on the other hand it allows you to navigate the menu structure. You can, for example, write code to selectively expand parts of the tree if relevant, or highlight all parent sections (i.e. the path) to create a "breadcrumbs" menu.

The key to this flexibility is the <view:relationships> tag. This tag lets you find out whether two menu items are related to one another, and if so, how.

In the following example, menu:item is used to retrieve the current menu item (that is, the menu item representing the current page view) and assign it to the variable base. view:iterate then iterates through the menu items in the menu and uses view:relationships to return the relationship between each menu item and base in the form of a Relation object.

<MENU:use id="menu" treeName="main">
  <MENU:item id="base"/>
  <VIEW:iterate id="menuItem">
    <VIEW:relationships id="relation" name="base"/>
    <li class="<%=relation.getState()%>">
      <%=menuItem.getText()%>
    </li>
  </VIEW:iterate>
</MENU:use>

The Relation object's getState() method returns one of the following values for each menu item:

isCurrent

This item is the current menu item.

isSibling

This item is a sibling of the current menu item

isChild

This item is a child of the current menu item.

isParent

This item is the parent of the current menu item.

isInPath

This item is an ancestor of the current menu item.

isParentInPath

This item's parent is an ancestor of the current menu item.

isDefault

This item is not closely related to the current menu item.

These states are not mutually exclusive: any parent node is also an ancestor, for example, and other duplications might occur. There are therefore boolean properties which can be read from the Relationships object for each state. For details, see the Javadoc for the class neo.util.tree.Relationships.

Other information that can be obtained from the Relationships object includes:

  • Does this item have any children? This may be so irrespective of whether or not the section referenced by the menu item has sub-sections, since the menu definition may explicitly exclude the creation of menu items for subsections. Conversely, article menu items can have children if they are explicitly defined in the menu resource.

  • Does this item have siblings, or is it the only child of its parent?

This technique can easily be used to create a "breadcrumbs" menu, for example:

<MENU:use id="menu" treeName="main">
  <MENU:item id="base"/>
  <VIEW:iterate id="menuItem">
    <VIEW:relationships id="relation" name="base"/>
    <UTIL:equal name="relation" property="ancestor" value="true">
      <%=menuItem.getText()%> &gt;
     </UTIL:equal>
  </VIEW:iterate>
</MENU:use>