Liferay provides out of the box layout templates which is sufficient for most of the requirements of a portal page. However, sometimes we may need to design custom page template which meets our requirements. This is possible with Liferay’s layout template plugin.

Following are the steps to create a liferay layout template using Liferay Developer Studio:

  • Create new plugin project from File >> New >> Liferay Plugin Project. Add project name, select plugin type as Layout Template and click on “Finish” button.

layoutTemplate1.PNG

  • Following image shows the folder structure of liferay layout template.

layoutTemplate2

  •  liferay-layout-templates.xml : This is the file specifies name and location of template files. also specifies thumbnail image location.
  • projectname.tpl : Generates the HTML structure(myLayoutTemplate.tpl).
  • projectname.wap.tpl : Generates HTML structure for mobile devices(myLayoutTemplate.wap.tpl).
  • projectname.png : Thumbnail image for layout template in .png format(myLayoutTemplate.png).
  • liferay-plugin-package.properties : Defines plugin project properties.

Designing Layout template:

  • Initially layout template files which are generated are empty. If we are using  Liferay IDE, we can make use of liferay’s default layout templates as reference and modify them according to our requirement. Click on design mode of .tpl file to add available sample design to our template file.
  • To create template structure manually, open .tpl file, add a  element as shown below. Element should include class, id and role attributes. Element value of should match id=main-content, role=main. Class attribute can be a custom value.
< div class="myLayoutTemplate" id="main-content" role="main">
 ...
</div>
  • To add a row, add a  element inside above created  element as shown below. The element class attribute value must match “portlet-layout row-fluid
< div class="portlet-layout row-fluid">
 ...
</div>
  • To add columns, add a div element for each column inside layout rowelement as shown below. Each column should have a unique ID attribute. Common convention is to use id like column-x, where x is an integer in incremental order.
< div class="portlet-column portlet-column-only span12" id="column-1">
    ...
</div>
  • Each column must specify class portlet-column. if a column is the first or last, or the only column in a row, that must specify either the portlet-column-first, portlet-column-last, or portlet-column-only CSS class respectively.
  • Each column  ’s class attribute must also specify a CSS class called span[width] where width can be in range 1-  to 12(Liferay 6.2 layout templates use Bootstrap’s 12 column grid system).
  • Finally, with each column  element, you must include a Velocity template directive to render each column’s portlets as shown below. This code renders portlet content as a portlet is added by the user to the column of a page.
$processor.processColumn("column-1",
 "portlet-column-content portlet-column-content-first")
  • The above method takes two arguments, column id and list of css classes. The css class attribute value “portlet-column-content” must be passed in the second argument. If the column is the first, last, or only column in a row, you also have to pass both “portlet-column-content” and “portlet-column-content-[first|last|only]” in the second argument, separated by a space.
  • Following is the complete code for a 1-3-1 template:
< div class="myLayoutTemplate" id="main-content" role="main">
 < div class="portlet-layout row-fluid">
 < div class="portlet-column portlet-column-only span12" id="column-1">
  $processor.processColumn("column-1", "portlet-column-content portlet-column-content-only")
 </div>
 </div>

 < div class="portlet-layout row-fluid">
 < div class="portlet-column portlet-column-first span4" id="column-2">
  $processor.processColumn("column-2", "portlet-column-content portlet-column-content-first")
 </div>

 < div class="portlet-column portlet-column-last span4" id="column-3">
  $processor.processColumn("column-3", "portlet-column-content portlet-column-content-only")
 </div>
 
 < div class="portlet-column portlet-column-last span4" id="column-4">
  $processor.processColumn("column-4", "portlet-column-content portlet-column-content-last")
 </div>
 </div>

 < div class="portlet-layout row-fluid">
 < div class="portlet-column portlet-column-only span12" id="column-5">
   $processor.processColumn("column-5", "portlet-column-content portlet-column-content-only")
 </div>
 </div>
</div>

Following is the template design:

layoutTemplate3

Embedding portlets to layout template :

Sometimes we may want to embed a portlet to our layout, which can not be removed by the administrator. To embed portlet to liferay template, we need following attributes:

  • portlet id : This is the value of  tag of portlet.xml file. For core portlets check : liferay-portal/portal-web/docroot/WEB-INF/liferay-portlet.xml
  • Instanceable : Specify whether multiple instances of the portlet can exist in the portal. This is specifies with keyword _INSTANCE_xxxx where xxxx is a random alphanumeric value. A custom instaceable portlet’s value may look like: portletID_WAR_webAppContext_INSTANCE_instanceID
  • Web Application Context : Web context name of portlet.
  • We need to pass fully qualified portlet id. This can be copied from advanced styling section of custom plugin portlets.

We need to pass fully qualified portlet ID to the method processor.processPortlet(“…”) as shown below.

//Core portlet(Search):
$processor.processPortlet("3")

//Instanceable core portlet(Navigation):
$processor.processPortlet("71_INSTANCE_abc8")

//Custom Portlet:
$processor.processPortlet("myCustomPortlet_WAR_myCustomPortletportlet_INSTANCE_abc1")

//Instanceable custom portlet:
$processor.processPortlet("myCustomPortlet_WAR_mycustomportlet_INSTANCE_abc1")

Following is the complete code:

< div class="myLayoutTemplate" id="main-content" role="main">
 < div class="portlet-layout row-fluid">
 < div class="portlet-column portlet-column-only span12" id="column-1">
   $processor.processColumn("column-1", "portlet-column-content portlet-column-content-only")
 </div>
 </div>

 < div class="portlet-layout row-fluid">
 < div class="portlet-column portlet-column-first span4" id="column-2">
   $processor.processPortlet("3")
   $processor.processColumn("column-2", "portlet-column-content portlet-column-content-first")
 </div>

 < div class="portlet-column portlet-column-last span4" id="column-3">
   $processor.processPortlet("71_INSTANCE_abc8")
   $processor.processColumn("column-3", "portlet-column-content portlet-column-content-only")
 </div>
 
 < div class="portlet-column portlet-column-last span4" id="column-4">
   $processor.processPortlet
   ("myCustomPortlet_WAR_myCustomPortletportlet_INSTANCE_abc1")
   $processor.processColumn("column-4", "portlet-column-content portlet-column-content-last")
 </div>
 </div>

 < div class="portlet-layout row-fluid">
 < div class="portlet-column portlet-column-only span12" id="column-5">
   $processor.processPortlet("AB_WAR_ABportlet")
   $processor.processColumn("column-5", "portlet-column-content portlet-column-content-only")
 </div>
 </div>
</div>

And the output:

layoutTemplate4

Check out all Liferay related posts.

Note: Version used: Liferay 6.2 + Apache Tomcat 7.