Rendering menus

Builder class Factory method Description

DefaultNavComponentBuilder

BootstrapViewElements.bootstrap.builders.nav()

Converts a Menu component to a Bootstrap nav.

PanelsNavComponentBuilder

BootstrapViewElements.bootstrap.builders.panels()

Converts a Menu component to a HTML5 nav where every group of Menu items is rendered as a panel with a heading.

BreadcrumbNavComponentBuilder

BootstrapViewElements.bootstrap.builders.breadcrumb()

Generates a breadcrumb for the selected items of a Menu.

Example

An example of generating a nav structure from a Menu.

Custom menu definition and rendering
import static com.foreach.across.modules.bootstrapui.ui.factories.BootstrapViewElements.bootstrap;

PathBasedMenuBuilder menu = new PathBasedMenuBuilder();
menu.item( "/one", "One", "#" ).order( 1 ).and()
    .group( "/two", "Two" ).order( 2 ).and()
    .item( "/two/one", "Sub item 1", "#" ).and()
    .item( "/two/two", "Sub item 2", "#" );

model.addAttribute(
    "customNav",
    bootstrap.builders.nav().menu( menu ).tabs().build( builderContext )
);
Thymeleaf template
<nav>
    <across:view element="${customNav}" />
</nav>

Supported nav styles

You can generate specific nav structures using the DefaultNavComponentBuilder by specifying a nav style.

Method CSS appended Remarks

simple()

Default mode.

navbar()

navbar-nav

tabs()

nav-tabs

pills()

nav-pills

stacked()

nav-pills nav-stacked

All NavComponentBuilder implementations also support custom HTML attributes to be configured directly on the root element.

Default menu conversion behaviour

When mapping a Menu onto a nav, the following rules are followed:

  • only 3 levels of items/groups are supported in the Menu

  • an item is always rendered as a single item, even if it has children

  • an item or group are only rendered if they are not disabled

  • when an item is selected, the item itself as well as all its parent will have the active css class

  • a group is only rendered if it has at least one non-disabled child

  • a group is rendered as a dropdown

  • a group inside a group is rendered as a labeled section in the dropdown

  • a group having only a single item is rendered as that single item unless the attribute nav:keepAsGroup is set

Menu item title

All nav related builders support message code snippets in Menu titles.

Putting for example #{my.code=Item title} as title property will be replaced by the Locale specific message for my.code or by Item title if that message code can’t be resolved

Replacing group label by the selected item

By default the label of a dropdown will always be the title of the group. If you want the label to be replaced by the label of the selected item, you should configure the NavComponentBuilder with replaceGroupBySelectedItem.

With replaceGroupBySelectedItem true, if no item is selected in the group, the dropdown label will still be the title of the group. If an item is selected however, the dropdown label will be the item label, unless the group itself has the attribute nav:keepGroupItem set to true.

Customizing nav rendering through the Menu

You can influence the generated output by setting reserved attributes on the Menu items.

Attribute names mentioned here are available as constants on the NavComponentBuilder class.

The following attributes are support on Menu items:

nav:icon

ViewElement or ViewElementBuilder to be prepended to the item text.

nav:iconOnly

Only applicable on a group. If an icon is set, this will render the group itself as only the icon.

nav:linkViewElement

ViewElement or ViewElementBuilder to use when rendering the link inside the list item. This will replace the standard link with the element generated. Note that any value for nav:icon will be ignored.

Possible child items will still be rendered as a nested unordered list if the item is a group. A custom link should handle opening the dropdown in that case.

nav:itemViewElement

ViewElement or ViewElementBuilder to use for rendering the entire list item of that Menu. The ViewElement should take care of the full rendering, including any possible children.

nav:keepAsGroup

Only applicable on a group. If set to true the group will always be rendered as a group, even though there is only a single item in it.

nav:keepGroupItem

Only applicable on a group and if replaceGroupBySelectedItem is set to true. If so and nav:keepGroupItem is set to true, the replace action will be suppressed and the group label will always be rendered.

NOTE: Attribute is only relevant for a DefaultNavComponentBuilder.

html:*

Any attribute with a name starting with html: will be added as html attribute to the list item. Name of the html attribute will be the menu attribute name without the html: prefix.

ViewElementBuilder attribute values

Some attributes support a ViewElementBuilder. When rendering using a ViewElementBuilder the ViewElementBuilderContext will have an attribute NavComponentBuilder.currentMenuItem that contains the Menu the builder is rendering.

Examples

Adding an icon

Adding an icon to an item or group is easily done by setting the nav:icon attribute with a ViewElement or ViewElementBuilder value.

Example adding an icon as attribute
import static com.foreach.across.modules.web.ui.elements.HtmlViewElements.html;

menu.item( "/dl", "Download", "#" )
    .attribute( NavComponentBuilder.ATTR_ICON, IconSet.iconSet( FONT_AWESOME_SOLID_ICON_SET ).icon( "download" ) )
    .order( 1 );
An icon based dropdown

If you set attribute nav:iconOnly to true, the dropdown will only render the icon for the group. If there is no icon value set on the group item, the dropdown will render the group title.

The children of the group (dropdown options) will always be rendered as full items.

If however the dropdown label is replaced by an item or the group only contains a single item, the item will also be rendered as only an icon.

Example creating a dropdown represented by a single icon
menu.group( "/options", "Options", "#" )
    .attribute( NavComponentBuilder.ATTR_ICON, IconSet.iconSet( FONT_AWESOME_SOLID_ICON_SET ).icon( "cog" ) )
    .attribute( NavComponentBuilder.ATTR_ICON_ONLY, true )
    .and()
    .item( "/options/dl", "Download", "#" )
    .attribute( NavComponentBuilder.ATTR_ICON, IconSet.iconSet( FONT_AWESOME_SOLID_ICON_SET ).icon( "download" ) );