Adding custom Layout type

Liferay has different types of pages. The default one is Layout - it’s standard, empty by default page, which is displayed in navigation menu. Portlets may be added to such page, themes and layouts may be also applied to this type of page. In most cases this page type is used.

But there are different page types, here are they:

  • Link to a Page of This Site - as the name says, this is a link to some page within site. Page of this type doesn’t have it’s own content, it’s used to redirect to some other page within the same site by clicking on this page in navigation menu
  • Link to URL - this is similar to previous type, but may refer to a page of some other site within portal, or even to some external URL
  • Panel - this type of page is used to work with different portlets on one and the same page. When you set page type to Panel in Site Pages menu, you can specify which applications (portlets) will be available on this panel page
  • Embedded - it’s a Liferay page, which contains IFrame, which displays content from specified URL. When you select Embedded page type, you may specify URL to display.

For most cases these page types are quite enogh for portal development. But sometimes there is a need to create a custom type of layout - for example, if you need to create layout as a link to some custom friendly URL, like products category. 

Fortunatelly, Liferay provides great opportunity to extend this funcitonality. See in original Liferay's portal.properties:

#
# Set the list of layout types. The display text of each of the layout types
# is set in content/Language.properties and prefixed with "layout.types.".
#
# You can create new layout types and specify custom settings for each
# layout type. End users input dynamic values as designed in the edit page.
# End users see the layout as designed in the view page. The generated
# URL can reference properties set in the edit page. Parentable layouts
# can contain child layouts. You can also specify a comma delimited list of
# configuration actions that will be called for your layout when it is
# updated or deleted.
#
layout.types=portlet,panel,embedded,url,link_to_layout

Let's create custom "link_to_category" layout type (similar to Liferay's link_to_layout). For this you need to overwrite 'layout.types' property in the portal.properties file of the hook module:

layout.types=portlet,panel,embedded,url,link_to_layout,link_to_category

and also specify the setting for new layout type:

layout.edit.page[link_to_category]=/portal/layout/edit/link_to_category.jsp
layout.view.page[link_to_category]=/portal/layout/edit/link_to_category.jsp
layout.url.friendliable[link_to_category]=false
layout.parentable[link_to_category]=false
layout.sitemapable[link_to_category]=false 

In the Language.properties hook set the name and description of created layout type:

layout.types.link_to_category=Link to Category
layout.types.link_to_category.description=Link to Category

In the specified JSP file (link_to_category.jsp) add required content for editing layout functionality. In my case it's the following:

<%@ page import="com.liferay.service.util.CategoryServiceUtils" %>
<%@ page import="com.liferay.service.util.Category" %>
<%@ include file="/html/portal/layout/edit/init.jsp" %>
<%
    Set<Category> categories = CategoryServiceUtils.getCategoryTrees();
    long categoryId = selLayout != null ? GetterUtil.getLong(selLayout.getTypeSettingsProperty("categoryId")) : 0;
%>
<aui:select label="link-to-category" name="TypeSettingsProperties--categoryId--" showEmptyOption="<%= true %>">
    <c:forEach var="category" items="${categories}">
        <aui:option label="${category.name}" value="${category.categoryId}" selected="${category.categoryId eq categoryId}"/>
    </c:forEach> 
</aui:select> 

After deploying hook with the changes above - you'll see the new layout type in Manage Pages section during adding/editing layout.  

After saving such layout custom 'categoryId' field will be saved into layout's typeSettings. Then it can be used within theme for displaying Layout in a different way.

Note 1: the "name" property of field should start with "TypeSettingProperties--" and end with "--" to be saved into Layout's TypeSettings. See in com.liferay.portlet.layoutsadmin.action.EditLayoutsAction#updateLayout:

UnicodeProperties typeSettingsProperties =
   PropertiesParamUtil.getProperties(
      actionRequest, "TypeSettingsProperties--");

Note 2: fields should be with namespaces. Either use AUI components, like in above example (as they generate them automatically), or add them manually to your components name, like:

<select name="_156_TypeSettingsProperties--categoryId--">
    <%-- ... --%>
</select>

, where 156 is GRUOP_PAGES portletID, see in com.liferay.portal.util.PortletKeys:

public static final String GROUP_PAGES = "156";

But it's better no not hard-code smiley

Hope, this will be helpful for you.

 

Regards,

Vitaliy

 

P.S. Read my Liferay book at https://www.aimprosoft.com/aimprosoft-products/liferay-book/

0