« Volver a Themes

Embedding a portlet in the theme

This article is out of date and contains incorrect information. For the most up to date documentation please visit https://dev.liferay.com

You can find documentation about embedding portlets at https://dev.liferay.com/develop/tutorials/-/knowledge_base/embedding-portlets-in-a-layout-template

This article needs updating. For more information, see Wiki - Need Updating.

Introduction #

Themes are developed using the Velocity template language. Liferay provides tools available within Velocity's context to perform special operations such as embedding a portlet. You can embed a built-in Liferay portlet or a plugin portlet, and you can also embed instanceable or non-instanceable portlets.

Here is an example of embedding the Navigation portlet into the theme.

Example #

Step One: Obtain the portlet nomenclature #

A portlet nomenclature consists of two parts: its unique ID string within the Liferay server, plus an instance identifier if necessary.

Every Liferay portlet has a unique Portlet ID, expressed as a String variable.

  • For out-of-the-box portlets, the ID is a numeric value.  For example, the Navigation portlet has an ID# of "73".
  • If the portlet is from a deployable plugin, the Portlet ID is more complex.  It will consist of the portlet's name, the string "WAR", and the name of the WAR file from which it is was deployed.  The complete form of the Portlet ID and how to construct one is defined in Theme Id or Portlet Id references in portal-ext.properties.

If the portlet is instanceable, then the nomenclature for the portlet must also contain an InstanceId in the form of a 4 character, alpha-numeric string, such as E3j7. The goal for this value is that it should be unique among the portlets of the same type (instance ID) on any given page.  The InstanceId is appended to the Portlet Id using the string "_INSTANCE_".

For our example, we are using the Navigation portlet, which has a Portlet ID of "73" and is instanceable, so we'll also need to give it an Instance Id as well.  Thus:

#set ($portlet_id = '73')
#set ($instance_id = 'E3j7')
#set ($my_portlet_id = "${portlet_id}_INSTANCE_${instance_id})

...which results in a portlet nomenclature of:

73_INSTANCE_E3j7

Step Two: Create the preferences for the portlet #

You can supply preferences for your embedded portlet as well.  Liferay provides a built-in VM variable called $velocityPortletPreferences for this purpose.

$velocityPortletPreferences is a Map<String, String>.  For each preference, pass its key string plus the value you desire.  The key may be one of Liferay's built-in portlet preference keys, or (for plugin portlets) one of your own that your portlet knows how to interpret.

For example, say we want to set the display style of the Navigation portlet to '1', and also we want the portlet to render itself borderless.  The latter is controlled by the key 'portlet-setup-show-borders'.  Thus:

#set ($VOID = $velocityPortletPreferences.setValue('display-style', '1'))
#set ($VOID = $velocityPortletPreferences.setValue('portlet-setup-show-borders', 'false'))}}}

Important: when you first pass preference values to a particular portlet instance on a page, Liferay will persist those values in the database.  From that point on, you cannot change the values in your Velocity macro.  See below for a discussion on how to cope with this feature.

Step Three: Create the runtime parameters #

In addition to preferences, you may also pass runtime parameters to your portlet, just as if they came from the query string.  These are set using basic URL parameter format, using "key=value" pairs separated by ampersands.  Your parameter names should not be namespaced to your portlet -- Liferay will take care of that for you.

For example, if you want to pass two parameters to your portlet called param1 and param2, you might construct the following string:

#set ($queryString = "param1=value1&param2=value2")

Step Four: Embed the portlet using //$taglibLiferay// #

Finally, we want to have the portlet invoked in some specific location on the theme. 

Liferay 5.2.x and lower #

Liferay pre-defined VM variable for this purpose is $taglibLiferay.  On its runtime() method, you must pass the complete nomenclature of the portlet as the first argument.  The optional second argument is the runtime parameters (i.e., the query string), and the optional third argument are the portlet preferences, which need to be serialized to a string.  Thus, for our example:

$taglibLiferay.runtime($myPortletId, $queryString, $velocityPortletPreferences.toString())

Liferay 6.x #

Liferay pre-defined VM variable for this purpose is $theme. On its runtime() method, you must pass the complete nomenclature of the portlet as the first argument. The optional second argument is the runtime parameters (i.e., the query string), and the optional third argument are the portlet preferences, which need to be serialized to a string. Thus, for our example:

$theme.runtime($myPortletId, $queryString, $velocityPortletPreferences.toString())

Step Five: Cleanup #

If you plan to add more than one portlet to the page in this way, make sure to reset the preferences you created for each portlet:

#set ($VOID = $velocityPortletPreferences.reset())

You can then proceed with a different portlet.

Complete Example #

Here is a complete example for the Navigation portlet (ID=73) with two preferences and no runtime parameters:

Liferay 5.2.x and lower #

#set ($VOID = $velocityPortletPreferences.setValue('display-style', '1'))
#set ($VOID = $velocityPortletPreferences.setValue('portlet-setup-show-borders', 'false'))
#set ($instanceId = 'E3j7')
#set ($myPortletId = "73_INSTANCE_${instanceId}")$taglibLiferay.runtime($myPortletId, '', $velocityPortletPreferences.toString())
#set ($VOID = $velocityPortletPreferences.reset())

Liferay 6.x #

#set ($VOID = $velocityPortletPreferences.setValue('display-style', '1'))
#set ($VOID = $velocityPortletPreferences.setValue('portlet-setup-show-borders', 'false'))
#set ($instanceId = 'E3j7')
#set ($myPortletId = "73_INSTANCE_${instanceId}")$theme.runtime($myPortletId, '', $velocityPortletPreferences.toString())
#set ($VOID = $velocityPortletPreferences.reset())

Changing the Portlet Preferences #

Sometimes you will put a portlet into your theme using one set of preferences, and later wish to change the preference values.  Many Liferay developers are frustrated to find that they can't do this easily.  The reason has to do with how Liferay persists portlet preferences - essentially, once they are written to the database (which will happen the first time the portlet is created on a page), you can no longer change them in Velocity.  Liferay will always use the stored preferences in favor of the preferences argument you pass.

There are two ways around this problem.

The first, for instanceable portlets, is simply to change the Instance ID to a new four-character string.  Liferay will consider it a new portlet and ignore its saved values.  Beware: those old values will still be lurking in the database, so if you ever do create a portlet with the old name, right down to the instance ID, those saved values will be used.

The second, suggested by Artur Linhart on the Liferay forums (see http://www.liferay.com/community/forums/-/message_boards/message/772138) is to have Velocity erase the old DB preferences before providing new ones.  Note that you do not want to make a habit of this, since it involves a DB operation that over time can prove very costly in terms of your site's performance.  The following Velocity macro will do the trick - note that it takes a fourth argument, which specifies whether any previous preferences should be erased.  It is suggested that you set up your VM code to pass 'true' only in development, and 'false' in production.

#macro (embedPortletUsing, $portletId, $requestVars, $preferences, $overrideDbPrefs)
  #if ($overrideDbPrefs)
    #set ($locPortletPreferenceService = $serviceLocator.findService("com.liferay.portal.service.PortletPreferencesLocalService"))
    #set ($locPlidLong = $getterUtil.getLong($plid))
    $locPortletPreferenceService.deletePortletPreferences(0, 3, $locPlidLong, $portletId)
  #end

  $taglibLiferay.runtime($portletId, $requestVars, $preferences)
#end

Known Restrictions in Staged Sites (6.1.x and lower versions) #

Embedded portlet preferences are not exported in Staged environments for versions prior to 6.2, so, you need to pass them the default configuration when you render the portlet in a theme, in a layout-template, web content, etc (https://issues.liferay.com/browse/LPS-33767)

0 archivos adjuntos
155393 Accesos
Promedio (12 Votos)
La valoración media es de 3.4166666666666665 estrellas de 5.
Comentarios
Respuestas anidadas Autor Fecha
This feature should be used carefully. As my... Sampsa Sohlman 23 de octubre de 2009 10:26
This description don't explain how extract the... Luca Preziati 14 de julio de 2010 6:55
Indeed. I do have the same issue about this. In... Nelson Vasconcelos 30 de julio de 2010 12:44
And where in the Velocity template (I am... Chris Becker 10 de agosto de 2010 13:26
Hello, i'm new in liferay i know this topic is... Tomas Guido 16 de diciembre de 2010 15:37
I read about velocity and put de code into the... Tomas Guido 20 de diciembre de 2010 10:46
I follow the instructions, it works for portlet... Lirone75 M. 17 de mayo de 2011 7:50
Hi, how do you do to extract the configuration... Adrien Duvignau 10 de noviembre de 2011 6:22
To extract configuration for an asset publisher... Petr Vlček 6 de diciembre de 2011 11:54
Does anyone have a problem position and code... Desarrollador Oficina Web 3 de octubre de 2012 4:39
Yes, I am having this problem in 6.1.1. I am... Spencer Mefford 8 de octubre de 2012 15:04
I am also having the same problem which Spencer... Jignesh Vachhani 29 de noviembre de 2012 22:56
I would be interested in a solution for that,... Patrick Warnecke 3 de diciembre de 2012 6:28
Very good! Steve Lan 6 de junio de 2013 3:42
when follow instruction above the footer only... Kelvin Do 29 de octubre de 2013 11:35
Its easiest to add a portlet into a piece of... Danny Stevens 7 de abril de 2014 21:04
I am still facing the portlet preferences issue... srikanth a 11 de abril de 2014 10:33
Please follow the bellow link.... Tariqul Islam 23 de febrero de 2015 11:02
Hi Tariq, I managed to embed a portlet in a... Nabil Bahtat 11 de agosto de 2015 13:43
I have a scenario where I am embedding weather... c s 30 de abril de 2014 12:29
Is there a special procedure for a targeted... Erik Fecher 16 de junio de 2014 6:08
Interesting. I've got a use case where I want... Jesse Page 3 de julio de 2014 8:00

This feature should be used carefully.

As my experience Liferay doesn't know if portlet is on theme. So cachefilter might cache wholepage when it should not. So this can produce strange looking problems.
Publicado el día 23/10/09 10:26.
This description don't explain how extract the preference to propagate the same portlet configuration in different page.
Publicado el día 14/07/10 6:55.
Indeed. I do have the same issue about this. In the mysql table "portletpreferences" I see that every page a different preference of the same same portlet instance.
Publicado el día 30/07/10 12:44 en respuesta a Luca Preziati.
And where in the Velocity template (I am assuming portal_normal.vm) does this code get placed? What determines the location on the page?
Publicado el día 10/08/10 13:26 en respuesta a Nelson Vasconcelos.
Hello, i'm new in liferay

i know this topic is old but i have the same problem, can someone tell me how to use this code, in the portal_normal like chris says or in other file and how to include in the template

thanks
Publicado el día 16/12/10 15:37 en respuesta a Chris Becker.
I read about velocity and put de code into the theme so the problem is solved
Publicado el día 20/12/10 10:46 en respuesta a Tomas Guido.
I follow the instructions, it works for portlet id = 73 but it doesn't work for my own developed portlet (id=1073 or id=idOfMyPortlet). What's the problem ?
Publicado el día 17/05/11 7:50.
Hi,

how do you do to extract the configuration of an asset publisher to propagate this same portlet on different pages ? Thanks
Publicado el día 10/11/11 6:22 en respuesta a Lirone75 M..
To extract configuration for an asset publisher portlet just choose Export/Import for given portlet and do a LAR export with settings export enabled. All settings can be found in downloaded LAR file. Hope it helps.
Publicado el día 6/12/11 11:54 en respuesta a Adrien Duvignau.
Does anyone have a problem position and code generation in version 6.1.1? To us the generated code of "theme.runtime" is generated outside the enclosing tag "<div> $ theme.runtime ... </ div>" -->> codePortlet <div></div>.
Publicado el día 3/10/12 4:39 en respuesta a Petr Vlček.
Yes, I am having this problem in 6.1.1. I am including the navigation portlet in the first column of a layout template, and rather than display in the column, it is rendered above the entire layout template, and stretches across all columns. I'm not sure why this is happening.
Publicado el día 8/10/12 15:04 en respuesta a Desarrollador Oficina Web.
I am also having the same problem which Spencer have.
I am using 6.1 EE GA2 and its rendering outside of layout.
please let us know how to work with ?
Publicado el día 29/11/12 22:56 en respuesta a Spencer Mefford.
I would be interested in a solution for that, too ....
Publicado el día 3/12/12 6:28 en respuesta a Jignesh Vachhani.
Publicado el día 6/06/13 3:42.
when follow instruction above the footer only display the portlet topper not the portlet body.
please advise?
Publicado el día 29/10/13 11:35.
Its easiest to add a portlet into a piece of web content and then add that to the theme: See https://www.liferay.com/web/barrie.selack/blog/-/blogs/embedding-a-portlet-in-we­b-content
To find your portlet's Id I found its easiest to add the portlet to a page, then go to the database and read off its properly formed Id from the portlet table, portletid column. This avoids misinterpreting the description given in http://www.liferay.com/community/wiki/-/wiki/Main/Theme+Id+or+Portlet+Id+referen­ces+in+portal-ext.properties
Publicado el día 7/04/14 21:04.
I am still facing the portlet preferences issue when i am adding the portlet in theme.
Boder is not setting to false in the preferences.
Publicado el día 11/04/14 10:33.
I have a scenario where I am embedding weather portlet in theme and I want the preferences to be personalized by the user logging in, not the entire site. Two questions,
Is this the right way to accomplish this?
What is the best way to have user preferences feed the portlet in the theme?

Thanks
Publicado el día 30/04/14 12:29.
Is there a special procedure for a targeted content portlet? For example, embedding a targeted content portlet on the default page of the site with custom links (not an "out-of-the-box" navigation portal). The string after _INSTANCE_ for the same portlet seems to change every time the site is accessed
Publicado el día 16/06/14 6:08.
Interesting. I've got a use case where I want to create 2 slide out menus on the side: Feedback and Quick Links. I don't want to use any hard links, or display a specific article within each, as I don't want that locked into a theme.

So I've dropped an asset publisher portlet into the Quick Links slide-out and a message board portlet into the Feedback slide-out so that I can configure independently.

The problem is, the configuration controls up by the topper don't initiate any of the pop-ups and/or drop-down menus. The hover effects still work and it shows as clickable on hover, but nothing happens. Has anyone come across this problem using this embed method? Are there additional portlet preferences that need to be set? Here is what I'm working with:

<!-- Alloy Toggler for Feedback and Quick Links -->
<div id="myToggler">
<div class="alloy-toggler-header toggler-header-collapsed">QL<p>Quick Links</p></div>
<div class="alloy-toggler-content toggler-content-collapsed">
#set ($VOID = $velocityPortletPreferences.setValue('portletSetupShowBorders', 'false'))
#set ($portlet_id = '101')
#set ($instance_id = "123abc678iuy")
#set ($my_portlet_id = "${portlet_id}_INSTANCE_${instance_id}")
$theme.runtime($my_portlet_id, "", $velocityPortletPreferences.toString())
$velocityPortletPreferences.reset()
</div>

<div class="alloy-toggler-header toggler-header-collapsed"><span class="icon-bullhorn">&nbsp;</span><p>feedback</p></div>
<div class="alloy-toggler-content toggler-content-collapsed">
#set ($VOID = $velocityPortletPreferences.setValue('portletSetupShowBorders', 'false'))
#set ($portlet_id = '29')
#set ($instance_id = "234abc678iuy")
#set ($my_portlet_id = "${portlet_id}_INSTANCE_${instance_id}")
$theme.runtime($my_portlet_id, "", $velocityPortletPreferences.toString())
$velocityPortletPreferences.reset()
</div>
</div>

Thanks,
-JP
Publicado el día 3/07/14 8:00.
Please follow the bellow link.
http://tariqliferay.blogspot.com/2015/02/how-to-add-portlet-in-liferay-them­e.html
Publicado el día 23/02/15 11:02 en respuesta a srikanth a.
Hi Tariq,
I managed to embed a portlet in a theme but I need to code different behaviour in my jsp according if my portlet is run from within a theme or run standalone (when put on a page). How to know I came from a theme ?
Thanks alot.
Nabil
Publicado el día 11/08/15 13:43 en respuesta a Tariqul Islam.