OpenCms provides an easy way to build dynamic page navigations. The tag <cms:navigation> can be used to get the navigation entries. We explore the requirements on a dynamic navigation, give an example navigation and support you with hints for building your own navigation.

Requirements for dynamic site navigations

A site navigation must adjust itself if the site structure changes. In OpenCms you can add or remove pages from your website dynamically. These changes should automatically mirror in the site navigation. If a page is removed, it should not appear anymore. If a page is added, it should be reachable via the navigation. In OpenCms you can write such dynamic navigations using the <cms:navigation> tag.

One navigation must be usable at several pages. Typically, you write one navigation (of one type) and display it on various pages of your website. The entries in the navigation fit to the very page, the navigation is placed.

There are differents types of navigations. Usually a webpage provides various different navigations. There is some top navigation, bringing you to the main pages of your website, there may be a side navigation that displays where the current page is placed in the navigation tree and that is used to navigate relative to that page. And last, there are breadcrumbs that tell you the way from the home page of your site to the current page. OpenCms provides support for all three of these navigations.

An example navigation

We examplify how to use the <cms:navigation> tag to produce a folder navigation. For a description on how to use the tag for other navigation types, see the tag's documentation.

Here's the code for the navigation:

<%@page taglibs="c,cms" %> 
<c:set var="navStartLevel">1</c:set>
<cms:navigation type="treeForFolder" startLevel="${navStartLevel}" endLevel="4" var="nav"/>
<ul class="nav-side list-group sidebar-nav-v1">		
	<c:forEach items="${nav.items}" var="elem">
		<li class='nav-side-level-${elem.navTreeLevel - navStartLevel} 
		           list-group-item 
		           ${!elem.navigationLevel && nav.isActive[elem.resourceName]?"active":""}'>
			<a href="<cms:link>${elem.resourceName}</cms:link>">${elem.navText}</a>
		</li>
	</c:forEach>
</ul>

The interesting spots of this JSP are the use of the <cms:navigation> tag and the iteration through the <c:forEach> loop. The <cms:navigation> tag exposes the attribute nav to the page scope. It is of type org.opencms.jsp.util.CmsJspNavigationBean. It's main property is items, that returns a list of org.opencms.jsp.CmsJspNavElements, but it also has some other properties, e.g., isActive as used also in the example. The list depends on the other attributes specified in the <cms:navigation> tag. In our example, we specify that:

  • we get only entries between the navigation levels 1 and (including) 4 by settings startLevel and endLevel accordingly.
  • we get the navigation of type treeForFolder, that means, all resources from the startLevel of the navigation, i.e., from level one in the example, plus all resource on the path of the currently requested page plus its direct subpages. But, all the subfolders only up to the specified endLevel.

By setting the type attribute differently, different lists of navigation elements are returned and these lists can also be adjusted by additional attributes as startLevel and endLevel. In our example, we could set, for example, additionally the attribute resource and provide a VFS path to a resource. Then the navigation would not be build relative to the currently requested resource, but to the on specified via the attribute.

In the <c:forEach> loop we render each item from the list of navigation entries. The entries provide various useful information on the entry. See the JavaDoc for an overview. In the example, we use the properties

  • navTreeLevel, to get the navigation level of the entry,
  • navigationLevel, to check if the entry is a navigation level,
  • resourceName, to get the link for the navigation,
  • navText, to get the navText property of the resource where the element links to.

Furthermore, we check if the currently rendered navigation entry links to the requested page. Therefor, we use the property isActive of the CmsJspNavigationBean (that is exposed by <cms:navigation>) to check if the navigation element's resource, matches the currently requested page.

CmsJspNavElement exposes more properties to build up navigations. Check the JavaDoc for details.

Which pages appear in a navigation?

The navigations build via the <cms:navigation> tag include only resources that have at least one of the properties NavText or NavPos set. Other resources are ignored. Furthermore, resources where the NavInfo property is set to ignoreInDefaultNav, are ignored. Read more on this here.

Hints for building your own navigation

Using <cms:navigation> is not very challenging. But building a good navigation is. Questions you should ask yourself, when implementing a navigation are:

  • How should I style my navigation? Styling a navigation is not trivial. At the above example, you see a lot of class attributes at the tags that do the styling for the example. If you work with nested lists for styling different levels of your navigation, be sure that in all cases every list has a closing tag.
  • How to get your navigation at your web pages? There are basically three options to get the navigation on your page:
    • You can include the navigation via <cms:include> into the template. Then it behaves as configured for all pages using the template. No further parameters can be set.
    • You make the navigation a dynamic function and add it to a (model) page. Then you may adjust its look via element settings or parameters passed to the dynamic function.
    • You make up an own content that renders the navigation. That provides you the most freedom to change and alter things.
  • How should I cache navigations? It is important to choose the right caching options for your navigation. Typically, use uri as flex cache directive at the JSP rendering the navigation by setting the cache property of the JSP to this value. Additionally, the directive container-element or user may be useful.