« Back to CMS Portlet (Legacy)

CMS Template (Velocity)

(Redirected from Journal Template (Velocity))

This article is legacy. The information is not up-to-date and should not be used unless you are on a legacy install of Liferay. For recent information, please see Web Content Management Portlet.

Introduction #

Journal/CMS Portlet was renamed to Web Content Portlet in Liferay 5.

This page is designed for people using the Liferay Journal (CMS Portlet) features which allows velocity macros to be used for displaying structured content.

The aim of this page to be a simple resource upon which non-programmers can create and adapt velocity templates within their CMS systems. Essentially it should provide a few examples and ideas on how you can get information out of Liferay and dynamically onto a webpage based upon the content you have created.

We'll talk a bit about Velocity and then create an example that allows someone to create an article with a drop down status list that is translated into a traffic-light image when displayed on the website.

Themes #

If you are looking for velocity information and what you can do with it when creating themes, this is not the document you want. However, take a look through this wiki page and then have a look at the class com.liferay.portal.velocity.VelocityVariables. Everything here applies, except you have whole bunch more stuff available to you when developing themes.

Assumptions #

I am assuming you know how to actually use the liferay CMS, how to create structured content and templates but wish to further your knowledge and learn how to use velocity.

Quick Velocity Overview #

Basically each velocity template is a plain text file with some simple 'special characters' in it. In the case of Liferay and other websites, those special characters are translated just prior to the server sending the requested web page to the clients browser. Velocity can be used to script any type of text file -- for instance, an email -- and in fact Velocity is also used for this within Liferay. I've used velocity to create test data for databases, transform telephone contact lists and so on. It's a useful piece of kit.

Basic Template #

So taking the example from a default Liferay installation, the developers kindly created a nice piece of content called SAMPLE-ARTICLE. Make sure you have access to the Guest community then you can search for this SAMPLE-ARTICLE. This article is based upon the structured content SAMPLE-STRUCTURE and is associated with two templates SAMPLE-VM-TEMPLATE and SAMPLE-XSL-TEMPLATE.

Once you have found the SAMPLE-ARTICLE, edit it and you will see that you can choose between the two templates, however choosing one or the other will not be visibly different. The difference is only the technology used to 'render' the SAMPLE-ARTICLE. One being XSL and the other VM, or Velocity Macro.

So open up the Template SAMPLE-VM-TEMPLATE and click on the 'Launch Editor' button. You will see a script pop up in a window. The script should look suspiciously like a web page with a load of lines which start with ## before it. Any line beginning with ## is a comment and is ignored by velocity. Lets take a look at the section

    <table border="1" cellpadding="8" cellspacing="0" width="600">
    <tr>
      <td>Sample Text</td>
      <td>$sample-text.getData()</td>
    </tr>
    <tr>
...

Here you can see we have access to the structured content, which has a row of data on it called sample-text. We have to ask sample-text for it's data and in fact we can simplify this quite a bit as velocity provides a bit of magic for us.

    <table border="1" cellpadding="8" cellspacing="0" width="600">
    <tr>
      <td>Sample Text</td>
      <td>$sample-text.data</td>
    </tr>
    <tr>
...

If you insert the sample article on a page somewhere and view it, then edit it to ensure it is using the SAMPLE-VM-TEMPLATE, you should see the article rendered in a big single column table.

What exactly is happening? Well you need to understand the relationship between Articles, Structures and Templates. The article is associated with a structure. The structure defines which fields are available to people creating articles. You can also choose a template, which defines how you want the article to appear.

Here you can see on the SAMPLE-ARTICLE that we have chosen a structure (SAMPLE-STRUCTURE), plus a template (SAMPLE-VM-TEMPLATE). In addition to providing us with fields to fill in, the structure also names those fields and we can access the fields in our velocity template using the special notation $ followed by the field name.

The following code snippet should actually be meaningful to you now. Quite simple we can access the fields provided by the structure and format them using plain old HTML.

    <table border="1" cellpadding="8" cellspacing="0" width="600">
    <tr>
      <td>Sample Text</td>
      <td>$sample-text.data</td>
    </tr>
    <tr>
...

Getting data out of different types of fields #

From the previous section you can open up the example and it will show you how to obtain data from the various types of fields available in the structured content.

  <table border="1" cellpadding="8" cellspacing="0" width="600">
    <tr>
      <td>$sample-text.data</td>
      <td>$sample-text-box.data</td>
      <td>$sample-text-area.data</td>
      <td><img src="$sample-image.data"/></td>
      <td>$sample-boolean-flag.data</td>
      <td>$sample-selection-list.data</td>
      <td>$reserved-article-id.data</td>
      <td>$reserved-article-version.data</td>
      <td>$reserved-article-title.data</td>
      <td>$reserved-article-create-date.data</td>
      <td>$reserved-article-modified-date.data</td>
      <td>$reserved-article-display-date.data</td>
      <td>$reserved-article-author-id</td>
      <td>$reserved-article-author-name</td>
      <td>$reserved-article-author-email-address</td>
      <td>$reserved-article-author-comments</td>
      <td>$reserved-article-author-organization</td>
      <td>$reserved-article-author-location</td>
      <td>$reserved-article-author-job-title</td>
      <td>$reserved-article-description</td>
    </tr>
  </table>

Note the special notation <strong>$reserved-article-XXXX</strong>. All of these give you access to the default fields such as the article ID, its title and description (abstract), creation date, last modified date and version number. All useful stuff, no?

More Detail #

Iterating #

One thing I didn't deal with in the last section was iterating, that is doing things one after another in a loop. This is clearly useful for walking over a list of items and doing stuff with each item. Take a look at this section.

    <tr>
      <td>Sample Multiple Selection List</td>
      <td>
        <b>
#foreach($selection in $sample-multi-selection-list.getOptions())
          $selection
          <br/>
#end
        </b>
      </td>
    </tr>

The special notation #foreach does exactly what it says on the tin. It moves, one item at a time over a list of items. In this case each item is called $selection and the list is grabbed from inside the multiple select box using the getOptions() method. This is diving into the realms of programming, but you should be able to mindlessly follow the example, a bit of copy and pasting and you'll be right! So if there are three items selected, the velocity macro above will produce something like this.

item1<br/>
item2<br/>
item3<br/>

Status Report Example #

Looking at the SAMPLE-ARTICLE you can the image is picked up quite cleverly as the URL of the image is stored one of the fields. As the URL is just a piece of text, we can manipulate it using velocity.

    <tr>
      <td>Image</td>
      <td><img src="$sample-image.getData()"/></td>
    </tr>

Let say we've uploaded three images to a gallery called 'images'. I can obtain the links to those three images and they happen to be in:

/image/image_gallery?img_id=1006
/image/image_gallery?img_id=1007
/image/image_gallery?img_id=1008

And in this case they are little traffic lights, red, amber and green.

Note: <strong>Must request friendly urls for images. That extra level of indirection would greatly enhance the galleries</strong>

Now I've created a drop down list box in my structured content as follows:

  ...
  <dynamic-element name='status' type='list'>
    <dynamic-element name='1007' type='OK'>  </dynamic-element>
    <dynamic-element name='1006' type='attention'>  </dynamic-element>
    <dynamic-element name='1008' type='problem'></dynamic-element>
  </dynamic-element>
  ...

And my velocity template can render the image as follows:

    ...
    <tr>
      <td>$title.getData()</td>
      <td>$detail.getData()</td>
      <td><img src="/image/image_gallery?img_id=$status.getData()"/></td>
      <td>$reserved-article-version.getData()</td>
    </tr>
    ...

Ok this is great, we've dynamically picked up some images, but what if I wanted the image to be displayed along with the text. Well as we cannot create friendly URLs for images, we're forced to do a bit of hard coding (hard-core liferay-ers may know of other ways, but I don;t). And to avoid making our template really messy, we'll create a little macro. Here are the full listings of my structured content and my template.

<root>
  <dynamic-element name='title' type='text'></dynamic-element>
  <dynamic-element name='detail' type='text_area'></dynamic-element>
  <dynamic-element name='status' type='list'>
    <dynamic-element name='OK' type='OK'>  </dynamic-element>
    <dynamic-element name='Attention' type='attention'>  </dynamic-element>
    <dynamic-element name='Problem' type='problem'></dynamic-element>
  </dynamic-element>
</root>
<html>
  <head>
    <title>$title.getData()</title>
  </head>
  <body>
#set ( $iurl = "/image/image_gallery?img_id=" )
#macro( tlight $tl-status )
 #if ($tl-status)
  #if ($tl-status.equals("OK"))
        <img src="$iurl 1007"/><br/>OK
  #elseif ($tl-status.equals("Attention"))
        <img src="$iurl 1006"/><br/>Attention
  #elseif ($tl-status.equals("Problem"))
        <img src="$iurl 1008"/><br/>Problem
  #end
 #else
        No Status Given
 #end
#end
    <table border="0" cellpadding="3" cellspacing="2" width="600">
    <tr>
      <td>Title</td>
      <td>Description</td>
      <td align="center">Status</td>
      <td>Version</td>
    </tr>
    <tr>
      <td>$title.getData()</td>
      <td>$detail.getData()</td>
      <td align="center" valign="center">
        #tlight( "$status.getData()" )
      </td>
      <td>$reserved-article-version.getData()</td>
    </tr>
    </table>
  </body>
</html>

Velocity macro includes #

Having put the traffic light image selector into a Velocity macro is really useful, we can extract that piece of code and place in a file of it's own so we can include it and re-use it anywhere. Let's face it dynamic web pages reporting traffic light status's are quite a useful thing to have! I've now created a new VM template called TRAFFIC-LIGHT-MACRO, however it is not associated with any structured content. The TRAFFIC-LIGHT-MACRO template looks like this:-

#set ( $iurl = "/image/image_gallery?img_id=" )
#macro( tlight $tl-status )
 #if ($tl-status)
  #if ($tl-status.equals("OK"))
        <img src="$iurl 1007"/><br/>OK
  #elseif ($tl-status.equals("Attention"))
        <img src="$iurl 1006"/><br/>Attention
  #elseif ($tl-status.equals("Problem"))
        <img src="$iurl 1008"/><br/>Problem
  #end
 #else
        No Status Given
 #end
#end

Notice there is no HTML in there at all. The SERVICES-BULLETIN macro is now quite short and sweet:-

<html>
  <head>
    <title>$title.getData()</title>
  </head>
  <body>
    <table border="0" cellpadding="3" cellspacing="2" width="600">
    <tr>
      <td>Title</td>
      <td>Description</td>
      <td align="center">Status</td>
      <td>Version</td>
    </tr>
    <tr>
      <td>$title.getData()</td>
      <td>$detail.getData()</td>
      <td align="center" valign="center">
        #parse("$journalTemplatesPath/TRAFFIC-LIGHT-MACRO")
        #tlight( "$status.getData()" )
      </td>
      <td>$reserved-article-version.getData()</td>
    </tr>
    </table>
  </body>
</html>

Services #

Creating a status report #

From the previous example, we can create individual pieces of content along with dynamically generated traffic light icons showing a graphical representation of the status. We've built ourselves a little macro which goes off and finds the right image based upon a piece of text and that text is selected from a drop down list box so the end user can easily see create pieces of structure content.

We've also created some external macros and included them.

It would be nice however, to use velocity to generate a list for us. Unfortunately within Journal, we have limited access to the underlying system and cannot really go any further, without dropping out to code. As this is a tutorial for non-programmers, I will address these issues with the liferay developers and see if we can get the desired hooks into a later version.

If you have some programming knowledge and want to rebuild yourself another installation of liferay take a look at the class com.liferay.portlet.journal.util.JournalVmUtil. I'd suggest using an xml tool that will allow you to query the rss feed as in the ABOUTUS-NEWS example which uses XSL.

Velocity Variables #

Looking at the source, the following variables being placed in the context, at least for 5.1.1. For technical details on the class type of each variable, see the method insertHelperUtilities(VelocityContext,String[]) in the class com.liferay.portal.velocity.VelocityVariables Additional variables are placed in the context by com.liferay.portlet.journal.util.JournalVmUtil.transform()

From JournalVmUtil #

  • request (not the http request so do a $request to see what's there)
  • company
  • companyId
  • groupId
  • journalTemplatesPath
  • locale
  • randomNamespace

From VelocityVariables #

utility classes #

  • arrayUtil
  • browserSniffer
  • dateFormats
  • dateTool
  • dateUtil
  • escapeTool
  • expandoColumnLocalService
  • expandoRowLocalService
  • expandoTableLocalService
  • expandoValueLocalService
  • getterUtil
  • htmlUtil
  • httpUtil
  • imageToken
  • iteratorTool
  • languageUtil
  • unicodeLanguageUtil
  • listTool
  • localeUtil
  • mathTool
  • numberTool
  • paramUtil
  • portalUtil
  • portal
  • prefsPropsUtil
  • propsUtil
  • portletURLFactory
  • randomizer
  • serviceLocator
  • sessionClicks
  • sortTool
  • staticFieldGetter
  • stringUtil
  • unicodeFormatter
  • validator
permissions #
  • accountPermission
  • commonPermission
  • groupPermission
  • layoutPermission
  • locationPermission
  • organizationPermission
  • passwordPolicyPermission
  • portalPermission
  • portletPermission
  • rolePermission
  • userGroupPermission
  • userPermission

tilesVariables #

  • attributeId / value pair

more work needs to be done to document the methods available in these objects

See Also #

Apache Velocity - Velocity User Guide

0 Attachments
134511 Views
Average (7 Votes)
The average rating is 4.0 stars out of 5.
Comments
Threaded Replies Author Date
Please update Velocity Variable section. It... Boden Larson August 20, 2008 11:02 AM
Yes, an update would be great. None of the... Thomas Kellerer February 2, 2009 9:38 AM
can anybody tell how to write velocity macro... Meenu charathu November 26, 2010 1:36 AM
I have placed Velocity Variables Explorer... Victor Zorin June 5, 2009 4:38 AM
Thanks Victor, The... Andreas Hoffmann February 7, 2010 2:04 AM
are you able to provide the source code for... Tim McGuire February 9, 2010 2:17 PM
Hi Victor, I visited your site at... Pius Sakia Macha April 20, 2010 4:29 PM
I've developed a portal that requires a hard... Chris Rail January 24, 2011 2:54 PM
Alright alright. I better understand why the... Chris Rail January 25, 2011 10:00 AM
I it possible to get the categories and tags of... Philipp Michael May 2, 2011 2:28 AM
For more on liferay ... Rohit Salecha May 9, 2011 11:31 PM

Please update Velocity Variable section. It seems like you're saying that variables like user are available in the Journal context.
Posted on 8/20/08 11:02 AM.
Yes, an update would be great. None of the above mentioned variables seem to work when using them in a Journal Template
Posted on 2/2/09 9:38 AM in reply to Boden Larson.
I have placed Velocity Variables Explorer portlet to online manual of my site, it automatically maintains all velocity variables available on Liferay portal and lists all public methods available for each of them.
It is available at the following URL:
http://www.myoffice24x7.com/web/manual/howto/explore-velocity-variables

(Unfo­rtunately, on public site I could not give access to the values of those variables, due to security reasons).
Posted on 6/5/09 4:38 AM.
Thanks Victor,

The http://www.myoffice24x7.com/web/manual/howto/explore-velocity-variables is a greate resource for those who employed Velocity as view technology in Liferay.

Spasibo. Molodec.
Posted on 2/7/10 2:04 AM in reply to Victor Zorin.
are you able to provide the source code for that "Velocity Variables Explorer portlet" ?
Posted on 2/9/10 2:17 PM in reply to Victor Zorin.
Hi Victor, I visited your site at http://www.myoffice24x7 to check if we can use any variable in CMS/Layout set for out Templates attached to web-content/structure. We want to display a signed-in user's attributes(e.g name,etc) to together with other static Web Content. I tried to use straight $user.getName(),$portalUtil.getUser($request), etc...without a success. Can you please pinpoint which variable/expression that we can use to achieve this in web content VM Template? This is for Liferay 5.2.3. Thanks Pius
Posted on 4/20/10 4:29 PM in reply to Victor Zorin.
can anybody tell how to write velocity macro for all structure fields
Posted on 11/26/10 1:36 AM in reply to Boden Larson.
I've developed a portal that requires a hard coded URL linking to an external website. Upon deployment, Liferay re-writes the URL I have enterer.

I came to this page looking for documentation on linking to external websites in Liferay, and the External Links section point to the Apache Velocity User Guide; which does not tell me how to include an external link.

Can anyone help me?
Please!
Posted on 1/24/11 2:54 PM.
Alright alright.

I better understand why the External Links section on this page links to the Apache Velocity User Guide.

Is anyone still able to help me with my inability to hard code a http:// URL inside a Liferay 6 Portlet? Or even point me towards the right direction?

To get a round my issue for now, I wrote a javascript function to forwards the user to the correct URL. I don't like writing "hack" code (although it's kind of fun).
Posted on 1/25/11 10:00 AM.
I it possible to get the categories and tags of the article? $reserved-article-tags.data and $reserved-article-categories.data don't work.
Posted on 5/2/11 2:28 AM.
For more on liferay

http://liferaydemystified.blogspot.com/
Posted on 5/9/11 11:31 PM.