Everyone has a top/primary navigation set of links on their site. In ServiceNow CMS it’s pretty easy to just use one of the out-of-box headers and utilize a navigation menu. However, the challenge comes when you want something that isn’t one of the pre-defined ServiceNow “types” (dropdown, horizontal, vertical, etc.)

For instance, what if you wanted to create something like this on your home page as sort of a “featured links” section:

cutsom_navigation_block
Sure, you could just hard-code it (dynamic block or HTML block), but then how easy will it be for a non-coder to keep it updated?

What if you wanted to have the menu serve up different items based on roles?

What if you needed it to be responsive and render differently on different viewports?

The way that I’ve found around this is to utilize a combination of a Navigation Menu + Dynamic Block.

Check out this code:

<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<!– Let's do a call to the specific navigation menu that we want to use –>
<g:evaluate>
var sectionGR = new GlideRecord('menu_section');
sectionGR.addQuery('sys_id', 'REPACE WITH YOUR SYS ID OF YOUR NAVIGATION MENU');
sectionGR.addQuery('active', 'true');
sectionGR.orderBy('order');
sectionGR.query();
<!– Let's also make sure the current user has the right role to see the specific menu item –>
function canViewMenu(gr) {
if (gr.logged_on == true)
if (!gs.isLoggedIn())
return false;
if (gr.roles.nil())
return true;
return gs.getUser().hasRole(gr.roles);
}
</g:evaluate>
<j:if test="${sectionGR.hasNext()}">
<j:set var="jvar_first_section" value="true" />
<!– Now we'll do the loop through the results –>
<j:while test="${sectionGR.next()}">
<!– Include the following standard UI Macro –>
<g:cms_menu_set_url_and_target />
<j:if test="${canViewMenu(sectionGR)}">
<!– Now we'll loop through the individual items of the menu –>
<g:evaluate>
var itemGR = new GlideRecord('menu_item');
itemGR.addQuery('menu_section', '${sectionGR.sys_id}');
itemGR.addQuery('active', 'true');
itemGR.orderBy('order');
itemGR.query();
</g:evaluate>
<j:set var="jvar_got_menu_items" value="false" />
<j:if test="${itemGR.hasNext()}">
<j:while test="${itemGR.next()}">
<j:if test="${canViewMenu(itemGR)}”>
<!– The following class tells it (in Bootstrap framework) to render 3 columns on desktop, 2 columns on mobile –>
<div class="col-lg-4 col-md-4 col-sm-6">
<a href="${itemGR.url}">
<img src="${itemGR.image.getDisplayValue()}"/></a>
<h6><a href="${itemGR.url}">${itemGR.name.getDisplayValue()}</a></h6>
</div>
</j:if>
</j:while> <!– End the items loop –>
</j:if>
</j:if>
</j:while> <!– End the menu loop –>
</j:if>
</j:jelly>

Simple right? It then lets you keep your code in one place and your content in another so it can render beautifully but is simple to manage. Both good things in my book.

Anything to add?

Author

With over a decade of experience, I have managed online marketing for a wide range of industries including biotech, high-tech, financial, higher education, non-profit, manufacturing, hardware providers, and startups. My specialty is helping business make the right turn with their online efforts focusing on lead generation and analytics.

Leave a Reply