Blogs
How to embed a Navigation Menu portlet in a theme's freemarker template and set portlet preferences
I recently came across a requirement to embed a Navigation Menu portlet in a Liferay 7.2 theme and to make the navigation display a specific set of pages.
Here are the steps that I took to accomplish this task:
- As an Administrator, go to the Control Panel and click on Site Builder > Pages
- Added three widget pages: P1, P2, and P3
- Clicked on "Go to Site" and then added a "Navigation Menu" widget to the home page
- Added a new navigation menu named "MyMenu" and added P1, P2, and P3
- Clicked on the "..." ellipses for the portlet and click on "Configuration"
- Clicked on the "Choose Menu" radio button
- Clicked on the "Select" button and clicked on "MyMenu"
- Clicked on the "Save" button
At this point the navigation menu looked like the following:
When I clicked the "Save" button, Liferay persisted some portlet preferences to the database. Knowing this, I shut down the portal in order to look at the $LIFERAY_HOME/data/hypersonic/lportal.script database in order to find out what the preferences looked like.
WARNING: Looking directly in the Liferay database isn't a best practice. I only show it here to help the reader understand what's going on behind the scenes. Olaf Kock developed the layout-info-web module that you can use to read the portlet preferences for everything on a page. You can also find out the preference names in the OSGi configuration Java source. For example: SiteNavigationMenuPortletInstanceConfiguration.java
After viewing the lportal.script file and searching for "MyMenu", I found this:
INSERT INTO SITENAVIGATIONMENU VALUES(0,'46b6d781-ed21-8c5d-dd36-6518a89bc1e1',36622,35019,20101,20130,'Admin User','2020-05-01 17:07:20.523000','2020-05-01 17:07:20.523000','MyMenu',0,'1',NULL)
I took note of "36622" as the primary key and then searched the file for that value:
INSERT INTO PORTLETPREFERENCES VALUES(1,36621,20101,0,3,18,'com_liferay_site_navigation_menu_web_portlet_SiteNavigationMenuPortlet_INSTANCE_RjnkBjOsupLW','<portlet-preferences><preference><name>displayStyle</name><value>ddmTemplate_NAVBAR-BLANK-FTL</value></preference><preference><name>siteNavigationMenuId</name><value>36622</value></preference><preference><name>displayDepth</name><value>0</value></preference><preference><name>rootMenuItemType</name><value>absolute</value></preference><preference><name>siteNavigationMenuType</name><value>-1</value></preference><preference><name>expandedLevels</name><value>auto</value></preference><preference><name>rootMenuItemLevel</name><value>0</value></preference><preference><name>displayStyleGroupId</name><value>35019</value></preference></portlet-preferences>')
With this information, I learned exactly which portlet preference name+value pairs that I needed for my embedded navigation portlet.
The next step was to create a custom theme:
npm install -g yo
yo liferay-theme
After setting the theme name, Liferay version, etc. the aforementioned command generated a theme project for me.
I then copied node_modules/liferay-frontend-theme-unstyled/templates/portal_normal.ftl to src/templates/portal_normal.ftl and modified it with the following:
<#assign myNavPrefs = freeMarkerPortletPreferences.getPreferences({"displayStyle": "ddmTemplate_NAVBAR-BLANK-FTL", "siteNavigationMenuId": "36622", "displayDepth": "0", "rootMenuItemType": "absolute", "siteNavigationMenuType": "-1", "expandedLevels": "auto", "rootMenuItemLevel": "0", "displayStyleGroupId": "35019"}) />
<@liferay_portlet["runtime"]
defaultPreferences="${myNavPrefs}"
instanceId="ABCDEF"
persistSettings=false
portletName="com_liferay_site_navigation_menu_web_portlet_SiteNavigationMenuPortlet"
/>
After deploying the theme with gulp deploy
I was able to apply the theme to my site, and the Navigation Menu portlet appeared on every page.
References:
- Setting Default Preferences for an Embedded Portlet
- GitHub Source: liferay-portal/modules/apps/frontend-theme/frontend-theme-classic/src/templates/portal_normal.ftl