Enterprise Java

Building dynamic responsive multi-level menus with plain HTML and OmniFaces

Recently, I had to create a responsive multi-level menu with JSF 2.2. Requirements: the menu should:
 
 
 
 
 
 
 
 
 

  • be created with dynamic structure from backend
  • be responsive, i.e. desktop- and mobile-friendly
  • have submenu items with navigation links
  • support touch events
  • support keyboard accessibility

PrimeFaces’ menus were not a choice. They can indeed be created programmatically by model, but:

  • they are not really responsive
  • submenu items only collapse / expand the submenus and can not contain navigation links

Well, why not to pick any jQuery based plugin for responsive multi-level menus? There are a lot of plugins. See Useful List of Responsive Navigation and Menu Patterns. I chose FlexNav.

But how to output the dynamic menu structure? ui:repeat is not a choice here because the structure (nested sub menus, etc.) is not known a priori. Fortunately, there is OmniFaces with o:tree, which allows to have full control over the markup of a tree hierarchy by declaring the JSF components or HTML elements in the markup. o:tree does not render any HTML markup by itself. Exactly what I need!

I ended up with this XHTML fragment mixing o:treeNode, o:treeNodeItem, o:treeInsertChildren and HTML elements defined by the mentioned FlexNav menu:

<h:outputScript library="js" name="jquery.flexnav.js"/>
<h:outputStylesheet library="css" name="flexnav.css"/>

<ul id="mainnavi" class="flexnav" data-breakpoint="640" role="navigation">
    <o:tree value="#{mainNavigationBean.treeModel}" var="item">
        <o:treeNode level="0">
            <o:treeNodeItem>
                <li class="item">
                    <a href="#{item.href}" title="#{item.title}">#{item.text}</a>
                    <o:treeInsertChildren/>
                </li>
            </o:treeNodeItem>
        </o:treeNode>
        <o:treeNode>
            <ul>
                <o:treeNodeItem>
                    <li>
                        <a href="#{item.href}" title="#{item.title}">#{item.text}</a>
                        <o:treeInsertChildren/>
                    </li>
                </o:treeNodeItem>
            </ul>
        </o:treeNode>
    </o:tree>
</ul>

<h:outputScript id="mainnaviScript" target="body">
    $(document).ready(function () {
        $("#mainnavi").flexNav({'calcItemWidths': true});
    });
</h:outputScript>

The OmniFaces’ TreeModel with menu items is created programmatically. The Java code looks like:

public TreeModel<NavigationItemDTO> getTreeModel() {
    // get menu model from a remote service
    NavigationContainerDTO rootContainer = remoteService.fetchMainNavigation(...);

    TreeModel<NavigationItemDTO> treeModel = new ListTreeModel<>();
    buildTreeModel(treeModel, rootContainer.getNavItem());

    return treeModel;
}

private void buildTreeModel(TreeModel<NavigationItemDTO> treeModel, List<NavigationItemDTO> items) {
    for (NavigationItemDTO item : items) {
        buildTreeModel(treeModel.addChild(item), item.getNavItem());
    }
}

And the end result (desktop variant):

responsiveMenu

Note that submenus are clickable and can be expanded on mouseover.

You see, JSF is flexible and sometimes you don’t need full-blown components. Have fun!

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

4 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
José Gregorio Castillo
José Gregorio Castillo
9 years ago

Hi Oleg, I was trying to understand this code, but I there’s something that I can not see: has your NavigationItemDto object the menu names and the menuItems in it?. My menu model has to entities, one for the Menu names and other ItemMenu, for the action (navigation to other place). The only thing that I see its to change my model to contain in one Entity the Menu name and the action, if this action is null or empty, means that is a name, so has children, wich has the action. Is this ok or am I wrong?. I… Read more »

Nathan Hughes
6 years ago

Hello,

I am trying to create a dynamic menu just like this on a wix website.

I am new to the coding for websites and and wondering if the code you have used here is something I could adopt in my wix code. Is that something you might have some insight into?

Thank you

Mücahit Ataşçi
Mücahit Ataşçi
5 years ago

Can you share NavigationItemDto code ?

Mücahit Ataşçi
Mücahit Ataşçi
5 years ago

it will be very useful if you helped me to create dynamic menu. Your Above code is clear, but have some trouble with NavigationItemDto . İt would be very useful if you share NavigationItemDto code with us,

thanks in advanced.,

Mücahit ATAŞÇİ

Back to top button