Liferay Application Display Templates (ADT) is great way to
change Portlet view dynamically without changing JSP pages code.
Liferay ADT use the Free Marker/Velocity Templates to change
Portlet view dynamically and this can be done by Liferay administrator from
Site Administration.
By Default Liferay have given ADT capability for few Portlets
which are in Liferay portal and we can change Portlets views dynamically by using
velocity/free marker templates.
Follow below Article Know about ADT
Liferay have given ADT API to implement ADT support for Out
of Box Portlet that is Custom Portlets.
Generally what are the variables or elements which required
in view logic we will group it and will be stored in template engine and whenever
we need in views we simply use reference names to access the variables or
elements from template engine and all these mechanism was implemented in
Liferay ADT API so that we can implement ADT Support to custom Portlets.
Liferay Have Template Handler which will take care of the
groping variables and store into template engine and at the time of render we
will use reference variable to access data from template engine and these template
engine are velocity or free marker that is why we will use velocity/free marker
templates in the ADT to change Portlet display dynamically.
Implementation ADT
Support to Custom Portlet
- Create Liferay MVC Portlet
- Implement Portlet Display Template Handler Java Class
- Register Portlet Display Template Handler Java Class
- Implement ADD_PORTLET_DISPLAY_TEMPLATE Permission to Custom Portlet
- Implement Configuration View to Portlet
- Implement View Logic to Read Configured Templates
Create Liferay MVC Portlet
Creating Liferay MVC Portlet is very straight forward step
and you can use Liferay IDE to create Liferay MVC Portlet.
Implement Portlet
Display Template Handler Java Class
To handle template variables we will use Portlet Display Template
Handler java class from ADT API and it will take care the template variables
which are required in the portlet display and these variables we will defined in the Portlet
Display Template Handler class.
We need to implement Custom Portlet Display Template Handler
class that should extend the BasePortletDisplayTemplateHandler.
BasePortletDisplayTemplateHandler java class consist many
methods so we will override some of the methods in the Custom Portlet Display Template
Handler class
The following are methods
getClassName(): This
will defined what type of entries you are rendering and typically its model class
name(Student.class, Employee.class)
getName():
Declares the name of your ADT type (typically, the name of the portlet).
getResourceName():
Specifies which resource is using the ADT (e.g. a portlet) for permission
checking.
getTemplateVariableGroups(): Defines the
variables exposed in the template editor.
The following is Example Implementation
public class ADTPOCPortletDisplayTemplateHandler extends
BasePortletDisplayTemplateHandler {
@Override
public String getClassName() {
// TODO Auto-generated method stub
return Student.class.getName();
}
@Override
public String getName(Locale arg0) {
// TODO Auto-generated method stub
return "ADTPOC Template";
}
@Override
public String getResourceName() {
// TODO Auto-generated method stub
return "ADTPOC_WAR_ADTPOCportlet";
}
public Map<String,
TemplateVariableGroup> getTemplateVariableGroups(
long classPK, String language, Locale locale)
throws Exception {
Map<String,
TemplateVariableGroup> templateVariableGroups =
super.getTemplateVariableGroups(classPK, language, locale);
TemplateVariableGroup templateVariableGroup =
templateVariableGroups.get("fields");
templateVariableGroup.empty();
templateVariableGroup.addCollectionVariable(
"students", List.class, PortletDisplayTemplateConstants.ENTRIES,
"student", Student.class, "curStudent", "name");
return templateVariableGroups;
}
}
|
Register Portlet
Display Template Handler Java Class
We already implemented Custom Register Portlet Display Template
Handler Java ClassAnd now we need to register this class name so that Portlet
will get ADT Capability to do this we will use Liferay-portlet.xml file
configuration file where we need to configure Custom Portlet Display Template Handler
Java Class and <template-handler/> is tag which should be enclosed by
<portlet/>
The following is example Configuration
<portlet>
<portlet-name>ADTPOC</portlet-name>
<icon>/icon.png</icon>
<configuration-action-class>com.adt.poc.config.ADTPOCConfigImpl</configuration-action-class>
<template-handler>com.adt.poc.template.ADTPOCPortletDisplayTemplateHandler
</template-handler>
<header-portlet-css>/css/main.css</header-portlet-css>
<footer-portlet-javascript>/js/main.js</footer-portlet-javascript>
<css-class-wrapper>ADTPOC-portlet</css-class-wrapper>
</portlet>
|
Implement “ADD_PORTLET_DISPLAY_TEMPLATE”
Permission to Custom Portlet
Since the ability to add ADTs is new to your portlet, we need
to configure permissions so that administrative users can grant permissions to
the roles that will be allowed to create and manage display templates. Just add
the action key ADD_PORTLET_DISPLAY_TEMPLATE to your portlet’s docroot/WEB-INF/src/resource-actions/default.xml
file
<?xml version="1.0"?>
<!DOCTYPE resource-action-mapping
PUBLIC "-//Liferay//DTD Resource Action
Mapping 6.2.0//EN" "http://www.liferay.com/dtd/liferay-resource-action-mapping_6_2_0.dtd">
<resource-action-mapping>
<portlet-resource>
<portlet-name>ADTPOC</portlet-name>
<permissions>
<supports>
<action-key>ADD_PORTLET_DISPLAY_TEMPLATE</action-key>
<action-key>ADD_TO_PAGE</action-key>
<action-key>CONFIGURATION</action-key>
<action-key>VIEW</action-key>
</supports>
<site-member-defaults>
<action-key>VIEW</action-key>
</site-member-defaults>
<guest-defaults>
<action-key>VIEW</action-key>
</guest-defaults>
<guest-unsupported>
<action-key>CONFIGURATION</action-key>
</guest-unsupported>
</permissions>
</portlet-resource>
</resource-action-mapping>
|
Implement
Configuration View to Portlet
To provide ADT Templet editor to create new ADT templates
will use Liferay Configuration page where we will provide template editor code
so that when we add new templates to Portlet, where you can see all
defined variables.
Follow the Article to Implement Portlet Configuration
Now Portlet configuration page(config.jsp) we need to
add following code so that it will provide template editor while design templates
and these can be accessed through Portlet configuration option by administrator.<
liferay-ui:ddm-template-selector/>
is tag which will take care all.
The following is example code in config.jsp page
<%@page import="com.liferay.portal.kernel.util.Constants"%>
<%@page import="com.liferay.portal.util.PortalUtil"%>
<%@ include file="init.jsp" %>
<%@page import="com.adt.poc.model.Student"%>
<%@page import="com.liferay.portal.kernel.template.TemplateHandlerRegistryUtil"%>
<%@page import="com.liferay.portal.kernel.template.TemplateHandler"%>
<liferay-portlet:actionURL portletConfiguration="true"
var="configurationURL" />
<aui:form action="<%= configurationURL %>" method="post"
name="fm">
<aui:input name="<%= Constants.CMD %>" type="hidden"
value="<%= Constants.UPDATE %>" />
<aui:fieldset>
<div class="display-template">
<%
TemplateHandler templateHandler =
TemplateHandlerRegistryUtil.getTemplateHandler(Student.class.getName());
%>
<liferay-ui:ddm-template-selector
classNameId="<%=
PortalUtil.getClassNameId(templateHandler.getClassName()) %>"
displayStyle="<%= displayStyle %>"
displayStyleGroupId="<%= displayStyleGroupId %>"
refreshURL="<%= PortalUtil.getCurrentURL(request) %>"
showEmptyOption="<%= true %>"
/>
</div>
</aui:fieldset>
<aui:button type="submit" name="submit"></aui:button>
</aui:form>
|
Implement View
Logic to Render Configured Templates
Now we need to provide logic that will render configure
templates to change Portlet view and this we will write in default view page of
Portlet.
When the ADT template is configures to Portlet then it will
render the configured template otherwise it will render default view.
The following is sample code.
<%@page import="java.util.ArrayList"%>
<%@page import="com.adt.poc.model.Student"%>
<%@page import="java.util.List"%>
<%@ include file="init.jsp" %>
This is the <b>Location Listing Portlet</b> in View mode.
<%
List<Student> students = new ArrayList<Student>();
for(int i=1; i<10; i++){
Student student = new Student();
student.setId(i);
student.setName("name"+i);
student.setCity("city"+i);
students.add(student);
}
%>
<%=portletDisplayDDMTemplateId%>
<c:choose>
<c:when test="<%= portletDisplayDDMTemplateId > 0 %>">
<%=
PortletDisplayTemplateUtil.renderDDMTemplate(pageContext, portletDisplayDDMTemplateId,
students) %>
</c:when>
<c:otherwise>
<table border="1">
<tr><th>Name</th><th>city</th></tr>
<%
for(Student student:students){%>
<tr><td><%=student.getName()%></td>
<td><%=student.getCity()%></td></tr>
<%} %>
</table>
</c:otherwise>
</c:choose>
|
Download ADT
Implemented Custom Portlet
ADT Implementation
in Custom Portlet Complete Example
In the example used Dummy Model class Student.java and while
create Student object simply use for loop to create student object and these
will be available as entries in the templates at the time of create new
templates for Portlet display.
ADTPOCPortletDisplayTemplateHandler.java
package com.adt.poc.template;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import com.adt.poc.model.Student;
import com.liferay.portal.kernel.language.LanguageUtil;
import
com.liferay.portal.kernel.portletdisplaytemplate.
BasePortletDisplayTemplateHandler;
import
com.liferay.portal.kernel.template.TemplateVariableGroup;
import com.liferay.portal.kernel.util.StringPool;
import
com.liferay.portlet.portletdisplaytemplate.util.
PortletDisplayTemplateConstants;
public class ADTPOCPortletDisplayTemplateHandler extends
BasePortletDisplayTemplateHandler {
@Override
public String getClassName() {
// TODO Auto-generated method stub
return Student.class.getName();
}
@Override
public String getName(Locale arg0) {
// TODO Auto-generated method stub
return "ADTPOC Template";
}
@Override
public String getResourceName() {
// TODO Auto-generated method stub
return "ADTPOC_WAR_ADTPOCportlet";
}
public Map<String,
TemplateVariableGroup> getTemplateVariableGroups(
long classPK, String language, Locale locale)
throws Exception {
Map<String,
TemplateVariableGroup> templateVariableGroups =
super.getTemplateVariableGroups(classPK, language, locale);
TemplateVariableGroup templateVariableGroup =
templateVariableGroups.get("fields");
templateVariableGroup.empty();
templateVariableGroup.addCollectionVariable(
"students", List.class, PortletDisplayTemplateConstants.ENTRIES,
"student", Student.class, "curStudent", "name");
return templateVariableGroups;
}
}
|
liferay-portlet.xml (/ADTPOC-portlet/docroot/WEB-INF/liferay-portlet.xml)
<?xml version="1.0"?>
<!DOCTYPE liferay-portlet-app
PUBLIC "-//Liferay//DTD Portlet Application
6.2.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_6_2_0.dtd">
<liferay-portlet-app>
<portlet>
<portlet-name>ADTPOC</portlet-name>
<icon>/icon.png</icon>
<configuration-action-class>com.adt.poc.config.ADTPOCConfigImpl</configuration-action-class>
<template-handler>com.adt.poc.template.ADTPOCPortletDisplayTemplateHandler
</template-handler>
<header-portlet-css>/css/main.css</header-portlet-css>
<footer-portlet-javascript>/js/main.js</footer-portlet-javascript>
<css-class-wrapper>ADTPOC-portlet</css-class-wrapper>
</portlet>
<role-mapper>
<role-name>administrator</role-name>
<role-link>Administrator</role-link>
</role-mapper>
<role-mapper>
<role-name>guest</role-name>
<role-link>Guest</role-link>
</role-mapper>
<role-mapper>
<role-name>power-user</role-name>
<role-link>Power
User</role-link>
</role-mapper>
<role-mapper>
<role-name>user</role-name>
<role-link>User</role-link>
</role-mapper>
</liferay-portlet-app>
|
default.xml (docroot/WEB-INF/src/resource-actions/default.xml)
<?xml version="1.0"?>
<!DOCTYPE resource-action-mapping
PUBLIC "-//Liferay//DTD Resource Action
Mapping 6.2.0//EN" "http://www.liferay.com/dtd/liferay-resource-action-mapping_6_2_0.dtd">
<resource-action-mapping>
<portlet-resource>
<portlet-name>ADTPOC</portlet-name>
<permissions>
<supports>
<action-key>ADD_PORTLET_DISPLAY_TEMPLATE</action-key>
<action-key>ADD_TO_PAGE</action-key>
<action-key>CONFIGURATION</action-key>
<action-key>VIEW</action-key>
</supports>
<site-member-defaults>
<action-key>VIEW</action-key>
</site-member-defaults>
<guest-defaults>
<action-key>VIEW</action-key>
</guest-defaults>
<guest-unsupported>
<action-key>CONFIGURATION</action-key>
</guest-unsupported>
</permissions>
</portlet-resource>
</resource-action-mapping>
|
config.jsp (/docroot/config.jsp)
<%@page import="com.liferay.portal.kernel.util.Constants"%>
<%@page import="com.liferay.portal.util.PortalUtil"%>
<%@ include file="init.jsp" %>
<%@page import="com.adt.poc.model.Student"%>
<%@page import="com.liferay.portal.kernel.template.TemplateHandlerRegistryUtil"%>
<%@page import="com.liferay.portal.kernel.template.TemplateHandler"%>
<liferay-portlet:actionURL portletConfiguration="true"
var="configurationURL" />
<aui:form action="<%= configurationURL %>" method="post"
name="fm">
<aui:input name="<%= Constants.CMD %>" type="hidden"
value="<%= Constants.UPDATE %>" />
<aui:fieldset>
<div class="display-template">
<%
TemplateHandler templateHandler =
TemplateHandlerRegistryUtil.getTemplateHandler(Student.class.getName());
%>
<liferay-ui:ddm-template-selector
classNameId="<%=
PortalUtil.getClassNameId(templateHandler.getClassName()) %>"
displayStyle="<%=
displayStyle %>"
displayStyleGroupId="<%=
displayStyleGroupId %>"
refreshURL="<%=
PortalUtil.getCurrentURL(request) %>"
showEmptyOption="<%= true %>"
/>
</div>
</aui:fieldset>
<aui:button type="submit" name="submit"></aui:button>
</aui:form>
|
ADTPOCConfigImpl.java (src/com/adt/poc/config/ADTPOCConfigImpl.java)
package com.adt.poc.config;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletConfig;
import com.liferay.portal.kernel.portlet.DefaultConfigurationAction;
import
com.liferay.portal.kernel.util.ParamUtil;
import
com.liferay.portlet.PortletPreferencesFactoryUtil;
public class ADTPOCConfigImpl extends DefaultConfigurationAction {
@Override
public void processAction(PortletConfig portletConfig,
ActionRequest actionRequest, ActionResponse actionResponse)
throws Exception {
// TODO Auto-generated method stub
String portletResource = ParamUtil.getString(actionRequest, "portletResource");
javax.portlet.PortletPreferences prefs = PortletPreferencesFactoryUtil.getPortletSetup(actionRequest, portletResource);
String displayStyle = ParamUtil.getString(actionRequest, "displayStyle");
prefs.setValue("displayStyle", displayStyle);
prefs.store();
super.processAction(portletConfig, actionRequest, actionResponse);
}
}
|
view.jsp(docroot/view.jsp)
<%@page import="java.util.ArrayList"%>
<%@page import="com.adt.poc.model.Student"%>
<%@page import="java.util.List"%>
<%@ include file="init.jsp" %>
This is the <b>Location Listing Portlet</b> in View mode.
<%
List<Student> students = new ArrayList<Student>();
for(int i=1; i<10; i++){
Student student = new Student();
student.setId(i);
student.setName("name"+i);
student.setCity("city"+i);
students.add(student);
}
%>
<%=portletDisplayDDMTemplateId%>
<c:choose>
<c:when test="<%= portletDisplayDDMTemplateId > 0 %>">
<%= PortletDisplayTemplateUtil.renderDDMTemplate(pageContext,
portletDisplayDDMTemplateId, students) %>
</c:when>
<c:otherwise>
<table border="1">
<tr><th>Name</th><th>city</th></tr>
<%
for(Student student:students){%>
<tr><td><%=student.getName()%></td>
<td><%=student.getCity()%></td></tr>
<%} %>
</table>
</c:otherwise>
</c:choose>
|
init.jsp (docroot/init.jsp)
<%@page import="com.liferay.portal.kernel.util.StringPool"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core"
prefix="c" %>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
<%@taglib uri="http://liferay.com/tld/portlet"
prefix="liferay-portlet" %>
<%@taglib uri="http://liferay.com/tld/security"
prefix="liferay-security" %>
<%@taglib uri="http://liferay.com/tld/theme"
prefix="liferay-theme" %><%@
taglib uri="http://liferay.com/tld/ui"
prefix="liferay-ui" %>
<%@taglib uri="http://liferay.com/tld/util"
prefix="liferay-util" %>
<%@page import="com.liferay.portlet.portletdisplaytemplate.util.
PortletDisplayTemplateUtil"%>
<%@page import="com.liferay.portal.kernel.util.GetterUtil"%>
<portlet:defineObjects />
<liferay-theme:defineObjects />
<%
String displayStyle =
GetterUtil.getString(portletPreferences.getValue("displayStyle", StringPool.BLANK));
long displayStyleGroupId =
GetterUtil.getLong(portletPreferences.getValue("displayStyleGroupId", null), scopeGroupId);
long portletDisplayDDMTemplateId =
PortletDisplayTemplateUtil.getPortletDisplayTemplateDDMTemplateId
(displayStyleGroupId,
displayStyle);
boolean showLocationAddress_view =
GetterUtil.getBoolean(portletPreferences.getValue("showLocationAddress", StringPool.TRUE));
%>
|
Usage of Portlet
Deploy Portlet into you portal server
After successful deployment you can see the Portlet in
sample category
Login as Admin and Drag and Drop Portlet in the page
The following is Default view of Portlet
Now go to Docbar Admin tab and click on Site Configuration
Configuration section you can see Application Display
Templates click on it
Now you can Add new ADT for our Custom Portlet by Select
Custom Portlet from Add Button Icon and Select Our Custom Portlet
Once we click on Add then it will launch Template Editor
there we need to design New Display to Custom Portlet By using Free
Marker/Velocity Templates. Once you design view then click on save then new ADT
Template will be created for Custom Portlet
In Setup tab you can see Display Template Drop down there
you can select our newly created Custom Portlet ADT then save it.
Once you apply new ADT then Portlet Display will be changed
such way you can create many Displays to custom Portlet using ADT.
Author