A PHP Error was encountered

Severity: Notice

Message: Undefined variable: flickr_photo

Filename: models/flickr_model.php

Line Number: 25

Two ways to embed web content in Liferay themes - Blog - Webdesign E-KON
No Dutch
Startpagina » Blog » Two ways to embed web content in Liferay themes Share/Bookmark

Two ways to embed web content in Liferay themes

Op 01 juni 2011 door Kristof Verbraeken in categorie Liferay

Introduction

Sometimes a client needs to be able to modify web content that appears on multiple pages. In some occasions you just can’t put the web content in the right place using the “basic” WCM features like Layout Templates and/or Journal Templates.

Consider things like a short introduction text in a header, a doormat, a footer, static navigation menu’s that rarely need to be updated, places for banners for temporary promotions and so on. What all these things have in common is that they don’t fit in the scope of Layout Templates or Journal Templates. You can’t reach the places I mentioned before with those facilities, because they mostly reside somewhere in the theme itself.

In this blog post/tutorial I will demonstrate and explain 2 ways to embed web content in a Liferay theme — using a demo theme which you can download below!

Demo theme

Take a look at the screenshot below:

The layout (theme) is made up out of four important areas:

  1. header: the area in the top of the layout;
  2. footer: the area in the bottom of the layout;
  3. sidebar: the area in the right center of the layout;
  4. content: the area in the left center of the layout. The layout of this area is determined by the configured Layout Template.

The first three areas (header, footer and sidebar) are the ones that should contain embedded web content which can be edited by the client through the Liferay Control Panel.

Create a journal article (or web content) for every area first as I have done in the screenshot below:

Note that I have used alphanumeric ID’s for the journal articles listed above instead of generated (numerical) ID’s. I will explain later why I’ve done that.

First way (complex)

The first way is based upon embedding the Web Content Display portlet: this portlet comes out the of box with Liferay.

Below is the configuration file (liferay-look-and-feel.xml) of the demo theme.

I’ve added the journal article ID of every journal article I need to embed in the theme (they are added as theme settings).

There’s also an extra setting portlet-setup-show-borders-default configured to hide the portlet wrapper of the embedded Web Content Display portlets.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE look-and-feel PUBLIC "-//Liferay//DTD Look and Feel 5.2.0//EN"
"http://www.liferay.com/dtd/liferay-look-and-feel_5_2_0.dtd">
<look-and-feel>
	<compatibility>
	<version>5.2.3</version>
	</compatibility>
	<company-limit>
	<company-includes />
	<company-excludes />
	</company-limit>
	<theme name="Demo" id="demo">
	<template-extension>vm</template-extension>
	<settings>
	<setting key="portlet-setup-show-borders-default" value="false" />
	<setting key="header-article-id" value="HEADER" />
	<setting key="sidebar-article-id" value="SIDEBAR" />
	<setting key="footer-article-id" value="FOOTER" />
	</settings>
	</theme>
</look-and-feel>

Next you need to add some Velocity code to the init_custom.vm file in the templates directory.

In this example I will only embed the sidebar as a separate Web Content Display portlet.

#set ($portletSetupShowBordersDefault = 
$theme_settings.getProperty("portlet-setup-show-borders-default"))
#set ($sidebarArticleId = $theme_settings.getProperty("sidebar-article-id"))

In this Velocity template the theme settings are loaded as Velocity variables.

When this file is set, we can proceed to the last step: modifying the portal_normal.vm file. In this file the init_custom.vm is executed thanks to the following statement:

#parse ($init)

The needed variables are injected in the theme and now we have all the information available that is needed to embed the web content.

You can now embed the web content with the following Velocity code:

$velocityPortletPreferences.setValue("portlet-setup-show-borders",
$portletSetupShowBordersDefault)
$velocityPortletPreferences.setValue("group-id", "$group_id")
$velocityPortletPreferences.setValue("article-id", "$sidebarArticleId")
$theme.runtime("56_INSTANCE_a0b1", "", $velocityPortletPreferences.toString())
#set ($VOID = $velocityPortletPreferences.reset())

First we need to configure the portlet preferences for the portlet we’re about to embed.

  • $portletSetupShowBordersDefault: injected setting from the XML configuration. This setting hides the portlet borders.
  • $sidebarArticleId: injected setting from the XML configuration. This variable contains the journal article ID of the sidebar.
  • $group_id: this variable is automatically set in the theme and contains the community ID.

Next, the portlet is embedded using the runtime method of the variable $theme. Notice that you have to provide this method with a portlet namespace, which in this case is 56_INSTANCE_a0b1. Make sure that this namespace always starts with 56_INSTANCE_ or else Liferay might embed a wrong portlet!

Notice the last line of code: the portlet preferences are reset. Always reset your portlet preferences after embedding the Web Content Display portlet or else you might get duplicate content in your theme! Also make sure that the portlet namespaces are unique within a page.

You might wonder why I’ve added all the variables as theme settings first. This approach makes the theme configurable. If something needs to be changed afterwards, you don’t need to modify the Velocity code, but just reconfigure the theme through the XML file liferay-look-and-feel.xml.

Also notice that I’ve used alphanumerical ID’s instead of numerical (generated) ID’s. I highly recommend using alphanumerical ID’s over the generated ones, simply because the generated ID’s might be different between other environments (development, integration, staging, production). If you use alphanumerical ID’s you don’t need to reconfigure the theme for every environment.

You can disable auto-generating ID’s with the following setting in portal-ext.properties:

journal.article.force.autogenerate.id=false

So far for the first way!

Second way (simple)

The second way makes use of the Liferay services. Instead of embedding a whole portlet in the theme we just load the web content to embed in the HTML of the theme.

The theme configuration was already discussed in the first way. In this explanation that same configuration is used again.

The init_custom.vm file must be modified again. In this example I will embed the header and footer content through this alternative way.

Take a look at the new content of the init_custom.vm file:

#set ($headerArticleId = $theme_settings.getProperty("header-article-id"))
#set ($footerArticleId = $theme_settings.getProperty("footer-article-id"))
#set ($headerContent = $journalContentUtil.getContent($group_id, $headerArticleId,
null, "$locale", $theme_display))
#set ($footerContent = $journalContentUtil.getContent($group_id, $footerArticleId,
null, "$locale", $theme_display))

Again, the theme settings are loaded as Velocity variables. Next, the web content service (JournalContentUtil) is used to load the content through the getContent method.

This method accepts 4 arguments:

  1. $group_id: the community ID of the web content article.
  2. $article_id: the web content article ID.
  3. $template_id: the web content template ID. You are free to use any web content template that is associated with the web content structure used by the article.
  4. $locale: the portal locale (which is set by default).
  5. $theme_display: the theme display object (which is set by default).

This web content is immediately set as Velocity variables.

Now in the portal_normal.vm file you just have to put these content variables in the right place and we’re done!

<div id="header">$headerContent</div>

Or:

<div id="footer">$footerContent</div>

That’s it for the second (simpler) way!

Conclusion

Both ways are very efficient and clean ways to embed web content in Liferay themes.

The second way is simpler than the first way, but you will not be able to embed the web content with the portlet wrapper. If this wrapper is needed or useful for any reason, I suggest you to use the first way.

In all the other cases, I recommend using the second (simpler) way.

Feel free to ask questions and don’t hesitate to download the demo theme below! This theme contains all the code discussed above.

Cheers!

Downloads

The two ways described above are applied in the demo theme which you can download below! Make sure to create three web content articles with ID’s HEADER, SIDEBAR and FOOTER. If these articles don’t exist, Liferay will tell you that the content is expired.



Reacties

Radoone ()

Hi!
I tried your theme or modify my theme according this setup. But I hasn't luck on Liferay 6. Do you know what must be different, or how to change to work on liferay 6 Thank you
Radovan

senja ()

hii..
i have a liferay portal and i give a sample web id for sample, but i didn't have idea how to change that web id for a seond time..
do you have idea/??

Kristof Verbraeken ()

Radoone,

I wrote this blog post from our own experiences with Liferay Portal. We haven't done a Liferay Portal 6 implementation yet...

I took some to install Liferay Portal 6.0.6 on a JBoss Application Server and started playing with the plug-ins SDK though.

I've created a theme for Liferay Portal 6 with embedded web content according to the methods I provided above. I did not cross any problems with these methods. I could just use the snippets above as I (or you) would do in Liferay Portal 5.

Screenshot:

http://www.e-kon.be/2010/files/liferay-embedded-web-content.png

You can download this Liferay 6 compatible theme I've created here:

http://www.e-kon.be/2010/files/test-theme-6.0.6.1.war

Also pay attention to the syntax of the snippets and especially the typecasts! Take a look at the JournalContentUtil service... If you don't pay attention to the typecasts there, that line will fail without you noticing it.

senja,

I'm sorry to say this, but I really don't understand what you mean?

NAJAR ()

Merci beaucoup j'en avais vraiment besoin, ça etait très util pour moi.

Je veux juste savoire comment vous avez pu faire pour utiliser un ID alphanumérique pour vos portlet, je n'arrive pas.

et SVP comment je peux faire pour integrer ma propre portlete que j'ai developpé avec PluginSDK par example.

Thinx

NAJAR ()

Thank you very much I needed it, it was very useful for me.

I just want to know how you were able to use an alphanumeric ID for your portlet, I can not.

and please how can I do to integrate my own portlets that I developed with PluginSDK for example.

Thinx

Kristof Verbraeken ()

Hello NAJAR,

I presume you're talking about this line of code:

$theme.runtime("56_INSTANCE_a0b1", "", $velocityPortletPreferences.toString())

The first parameter of the runtime method of the theme object is the portlet namespace.

As you can see, this namespace is made up different parts, in this example:

# 56: the portlet ID, which in this case is the portlet ID of the Web Content Display portlet.
# INSTANCE: this is always included in the portlet namespace.
# a0b1: this is added to create a unique portlet namespace on every page.

For example: if you want to embed 2 Web Content Display portlet in one theme, you have to make sure that their portlet namespaces are unique (different from each other) and the runtime method should still be able to recognise which portlet to embed. In this case both portlet namespaces would start with "56_INSTANCE_" while the last characters should make them unique, for example "56_INSTANCE_a0b1" and "56_INSTANCE_c3d4".

To embed your own custom portlets you can also use this way. Just replace the "56" in the example above with your custom portlet ID. If you're using portlet plug-ins from the plug-ins SDK the complete portlet namespace is usually in the form of "portletname_WAR_portletnameportlet". I suggest you use the following line of code to embed custom portlets:

$theme.runtime("portletname_WAR_portletnameportlet", "", $velocityPortletPreferences.toString())

I'm a little short on time at the moment to test these things out, but I guess the above line might just work.

Please let us know if you managed to embed a custom portlet like this.

Kind regards,
Kristof

NAJAR ()

Thank you vary very much Kristof !

For more information :

http://www.scribd.com/doc/57715749/5/Embedding-non-instanceable-portlets-in-theme

Kind regards.

Kristof Verbraeken ()

Hey,

Thanks for coming back to share that link.

Quote:

The portlet ID is shown in the JavaScript URL, as displayed in the following screenshot.In this case, the portlet ID is
sample_WAR_sampleportlet_INSTANCE_WI4g

Close to what I said. :-)
.
Ciao,
Kristof

sonika ()

Hi,

I want to add web content display portlet for header (need to add two buttons and search portlet) and footer(need to add 3 links). I tried as suggested, but I am getting three new web content portlets and not the one created initially with id's "header"
and "footer". Following is code I appended in portal_normal.vm :

$velocityPortletPreferences.setValue("portlet-setup-show-borders",
$portletSetupShowBordersDefault)
$velocityPortletPreferences.setValue("group-id", "$group_id")

$velocityPortletPreferences.setValue("article-id", "$sidebarArticleId")
$theme.runtime("56_INSTANCE_a0b1", "", $velocityPortletPreferences.toString())

$velocityPortletPreferences.setValue("article-id", "$headerArticleId")
$theme.runtime("56_INSTANCE_c3d4", "", $velocityPortletPreferences.toString())

$velocityPortletPreferences.setValue("article-id", "$footerArticleId")
$theme.runtime("56_INSTANCE_e5f4", "", $velocityPortletPreferences.toString())

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

The Portlet namespaces - 56_INSTANCE_a0b1, 56_INSTANCE_c3d4, 56_INSTANCE_e5f4, I have chosen randomly. How should I give the portlet namespace in the theme.runtime. Is there any place I create portlet namespace or its set by Liferay if yes, then from where I can retreive the portlet namespace value.


Regards
Sonika

TriaraApedia ()

6lbxcr41 bitch aishwarya rai nude aishwarya rai nude photos gf7m5nbr http://hubadasites.com/aishwarya_rai_nude/ ypakzizz eva mendes nude we own the night eva mendes nude 8ps8vtk0 http://hubadasites.com/eva_mendes_nude/ d13kx0ve paris hilton nude pic paris hilton nude video czfeix2z http://hubadasites.com/paris_hilton_nude/ 7hd7nj5n sammi sweetheart nude pics sammi sweetheart giancola nude jdecex93 http://hubadasites.com/sammi_sweetheart_nude/ qk3yc9om amber heard is nude amber heard nudes 8rc76651 http://hubadasites.com/amber_heard_nude/

slot8 ()

?????? ????? ? ??????? ?????? ???? ?????? ?????? ???????? ??????? ???????? fairy land ????????? ????? ?? ???????? ?????? ?????? ???????? ???? ????????? ? ??? ??????????? ? ??? ??? ???????? ?????? ????? ??????? ???????? ???????? qiwi ??????? ????? ????????

Reactie plaatsen

( Je email is veilig bij ons! )

A PHP Error was encountered

Severity: Warning

Message: Invalid argument supplied for foreach()

Filename: views/index.php

Line Number: 181