Skip to content
OpenCms documentation
OpenCms documentation

Building page navigation

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

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 be mirrored automatically in the site navigation. If a page is removed, it should not appear anymore. If a page is added, it should be reachable via navigation. In OpenCms you can write such dynamic navigation using the <cms:navigation> tag.

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

There are differents types of navigation. A webpage can often provide various approaches to navigation: there could be top navigation, bringing you to the main pages of your website, there may be 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 navigational types.

We exemplify how to use the <cms:navigation> tag to produce 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 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. Its 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 such 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 built relative to the currently requested resource, but to the one 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. Therefore, 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 navigation. Check the JavaDoc for details.

Navigation built via the <cms:navigation> tag includes 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.

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

  • How should I style my navigation? Styling navigation is not trivial. In the above example, you see a lot of class attributes in 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 navigation on your web pages? There are basically three options to get navigation on your page:
    • You can include navigation via <cms:include> into the template. Then it is 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 your own content that renders the navigation. That gives you the most freedom to change and alter things.
  • How should I cache navigation? It is important to choose the right caching options for your navigation. Typically, use uri as a flex cache directive in 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.