DxpLife The practical Liferay DXP knowledge hub
Talk to us

Home/Knowledge Hub/Frontend & presentation

Frontend & presentation

Widget Templates in Liferay 7.4

Application Display Templates, FreeMarker, presentation, reuse, security and best practices

In-depth guideFoundation65 sections~16 min read
In this resource. Customize how widgets render without touching Java: Application Display Templates, FreeMarker syntax and context, collections, localization, security and performance — and how templates compare with fragments and themes.

Introduction

A Liferay widget generally contains two broad concerns:

  1. Business/data logic
  2. Presentation logic

For example, an Asset Publisher may retrieve a collection of assets and render them using its default presentation. Conceptually:

Diagram
Widget
  |
  +--> Retrieve Data
  |
  +--> Default Rendering

Sometimes the data retrieval is correct, but the presentation must change. For example, instead of:

Code
Title
Description

Title
Description

Title
Description

we may want:

Diagram
+------------+  +------------+  +------------+
|   Image    |  |   Image    |  |   Image    |
|   Title    |  |   Title    |  |   Title    |
|   Button   |  |   Button   |  |   Button   |
+------------+  +------------+  +------------+

A Widget Template provides this presentation customization.

Application Display Templates

Widget Templates are closely related to what Liferay traditionally called:

Application Display Templates (ADTs)

The fundamental idea is:

Widget Data + Template = Custom Presentation

Therefore, the same widget data can have multiple visual representations.

Why Use Widget Templates?

Widget Templates are useful when:

  • Default widget rendering is not suitable
  • A list should become cards
  • Additional HTML structure is needed
  • Business data should remain unchanged
  • The same display should be reusable
  • A developer wants to avoid modifying Liferay core JSPs

The design principle is:

Separate Data Retrieval from Presentation

Simple Architecture

Without a custom template:

Diagram
Database
   |
   v
Liferay Service
   |
   v
Widget
   |
   v
Default Display

With a Widget Template:

Diagram
Database
   |
   v
Liferay Service
   |
   v
Widget
   |
   v
Widget Template
   |
   v
Custom HTML

The Widget Template operates mainly at the presentation layer.

Presentation Separation

Conceptually:

D = Data
T = Template
R = Rendered Output

Then:

R = T (D)

The same data:

D

can therefore be rendered by:

T1(D) = List
T2(D) = Cards
T3(D) = Grid

without changing the underlying data.

Example

Suppose an Asset Publisher returns three news articles. The default presentation may be:

Code
Quantum Computing Workshop

New Quantum Research Published

Photonics Laboratory Opens

A Widget Template could instead produce:

+-----------------------+
| Image |
| Quantum Computing |
| Workshop |
| [Read More] |
+-----------------------+
+-----------------------+
| Image |
| New Quantum Research |
| Published |
| [Read More] |
Diagram
+-----------------------+

The content has not changed. Only its presentation has changed.

Where Widget Templates are Managed

Depending on the Liferay 7.4 release and site configuration, Widget Templates can be managed through the site administration interfaces associated with design/templates. The typical workflow is:

Diagram
Site Administration
      |
      v
Design / Templates
      |
      v
Widget Templates
      |
      v
Create Template

Creating a Widget Template

The general process is:

  1. Open the appropriate Site Administration area.
  2. Navigate to Widget Templates.
  3. Click Add.
  4. Select the widget/application for which the template is being created.
  5. Enter a template name.
  6. Write the template logic.
  7. Save the template.
  8. Add/configure the target widget on a page.
  9. Select the new Widget Template from the widget’s display configuration where supported.

Template Language

FreeMarker is the primary templating language used for many modern Liferay templates. FreeMarker uses syntax such as:

FreeMarker
${variable}

for values. Conditions use:

XML / HTML
<#if condition>
    ...
</#if>

Loops use:

XML / HTML
<#list entries as entry>
    ...
</#list>

Basic FreeMarker Example

Consider:

XML / HTML
<h2>My Widget Template</h2>

<#if entries?has_content>

    <ul>

       <#list entries as entry>

           <li>
              ${entry}
           </li>

       </#list>

    </ul>

</#if>

The exact objects available in the template depend on the widget.

Template Context

A Widget Template executes with a template context. Conceptually:

Context = {variables, objects, services, helpers}

The exact variables depend on the application. For example, a collection-oriented widget might expose something conceptually similar to:

Code
entries

The template then iterates through those entries.

Using Variables

Basic FreeMarker output:

FreeMarker
${title}

Another example:

XML / HTML
<h2>${title}</h2>

A variable should be checked where it may be absent. For example:

XML / HTML
<#if title??>
    <h2>${title}</h2>
</#if>

The operator:

Code
??

checks whether a value exists.

Default Values

FreeMarker can provide a fallback value. Conceptually:

FreeMarker
${title!"Untitled"}

If:

title = ∅

then:

Code
Untitled

is displayed. This improves template robustness.

Conditional Rendering

Example:

XML / HTML
<#if entries?has_content>

    <p>Entries are available.</p>

<#else>

    <p>No entries found.</p>

</#if>

This prevents blank or confusing output.

Looping Through Entries

A common Widget Template operation is:

XML / HTML
<#list entries as entry>

    <div class="item">

       ${entry}

    </div>

</#list>

Conceptually:

Entries = {E1 , E2 , . . . , En }

and the template performs:

∀Ei ∈ Entries, Render(Ei )

Card-Based Example

Suppose a widget exposes a list of items. A card-style template might conceptually be:

XML / HTML
<div class="row">

<#list entries as entry>

    <div class="col-md-4">

       <div class="card">

           <div class="card-body">

              <h3>
                  ${entry}
              </h3>

           </div>

       </div>

    </div>

</#list>

</div>

This demonstrates the primary purpose:

Same Entries → Different HTML Structure

Using Clay/Bootstrap Classes

Liferay’s frontend uses Clay and Bootstrap-oriented styling conventions.

A template can use available classes such as:

XML / HTML
<div class="container">

    <div class="row">

       <div class="col-md-6">

           Content

       </div>

    </div>

</div>

This helps custom output visually integrate with the surrounding Liferay UI.

Example: Grid Layout

XML / HTML
<div class="row">

<#if entries?has_content>

    <#list entries as entry>

       <div class="col-lg-4 col-md-6 mb-4">

           <div class="card h-100">

              <div class="card-body">

                  <h4 class="card-title">
                     ${entry}
                  </h4>

              </div>

           </div>

       </div>

    </#list>

</#if>

</div>

Widget Configuration

After creating a template, the relevant widget normally needs to be configured to use it. Conceptually:

Diagram
Page
 |
 v
Diagram
Widget
 |
 v
Configuration
 |
 v
Display / Template
 |
 v
Custom Widget Template

This allows the same widget to use different templates in different contexts.

Reusable Presentation

Suppose a template called:

Code
Corporate Card Layout

is created. It can potentially be reused by multiple instances of the supported widget. Thus:

One Template → Multiple Widget Instances

This improves consistency.

Widget Templates and Asset Publisher

Asset Publisher is a classic use case for display templates. Conceptually:

Diagram
Asset Publisher
     |
     +--> Web Content
     +--> Documents
     +--> Blogs
     +--> Other Assets
     |
     v
Widget Template
     |
     v
Custom Display

For example, assets could be rendered as:

  • News cards
  • Image gallery
  • Featured content
  • Compact list
  • Timeline

Widget Templates and Asset Lists

A collection-oriented widget can provide data while the template controls how that data appears. This separation can be expressed as:

Selection Logic̸ = Presentation Logic

The widget selects entries. The template renders entries.

Localization

A production template should consider multilingual portals. Instead of hard-coding:

Code
Read More

a localized value should be used where the template context and supported APIs provide localization helpers. Conceptually:

Language Key → Current Locale → Localized Text

For example:

Diagram
English -> Read More
French  -> Lire la suite
Hindi   -> Aur padhen

Escaping Output

Output security is important whenever dynamic values are rendered. Conceptually:

UserInput → Escape → HTML

rather than:

UserInput → RawHTML

because unsafe output can contribute to cross-site scripting (XSS) risks.

FreeMarker Restrictions

A template environment should not be viewed as unrestricted Java execution. For security reasons, Liferay controls what can be accessed from templates. A template should primarily perform:

  • Presentation
  • Formatting
  • Simple conditions
  • Iteration

It should not become a replacement for the application’s service layer.

Bad Template Design

A poor design is:

Diagram
Widget Template
    |
    +--> Complex Database Logic
    |
    +--> Remote API Calls
    |
    +--> Business Transactions
    |
    +--> Complex Permission Logic

A better design is:

Diagram
Service / Widget
     |
     v
Prepared Data
     |
     v
Widget Template
     |
     v
Presentation

Thus:

Template ≈ Presentation Logic

Avoid Heavy Processing

Suppose a template renders:

N = 100

entries. If each iteration performs an expensive operation of cost:

C

the total cost becomes approximately:

T =N ×C

If:

C = 50ms

then:

T = 100 × 50ms = 5000ms

or approximately:

5 seconds

before considering other processing. Therefore, expensive service calls inside loops should be avoided.

N+1 Problem

Consider:

XML / HTML
<#list entries as entry>

    getAdditionalData(entry)

</#list>

If each item causes a database or service call:

1 initial request + N additional requests

then:

1 + N

operations are performed. For:

N = 100

this becomes:

101

operations. Prepare data efficiently before rendering wherever possible.

Template Error Handling

A template can fail if it assumes a value always exists. For example:

FreeMarker
${entry.title}

may fail or behave unexpectedly if the expected value is unavailable. Safer logic can include:

XML / HTML
<#if entry.title??>
    ${entry.title}
</#if>

or an appropriate fallback.

Inspecting Available Variables

When developing a template, determine which variables the selected widget exposes. Conceptually:

Diagram
Widget
 |
 +--> Template Context
      |
      +--> entries
      +--> request
      +--> themeDisplay
      +--> helper objects
      +--> application-specific values

The exact set varies by widget and Liferay version. Use the editor’s available variable/reference information and official documentation instead of guessing object methods.

themeDisplay

In supported template contexts, themeDisplay provides information related to the current portal request. Conceptually it can provide access to contextual information such as:

  • Current user
  • Company
  • Site/group
  • Locale
  • Portal URL context

Example concept:

XML / HTML
<#if themeDisplay??>

    Current Site Context Available

</#if>

The actual accessible methods depend on the template environment.

URLs in Templates

A template often needs links. For example:

XML / HTML
<a href="${viewURL}">
    Read More
</a>

The URL should normally come from the widget/template context rather than being hard-coded. Bad:

XML / HTML
<a href="/web/guest/news?id=123">

Better:

XML / HTML
<a href="${viewURL}">

This improves portability.

Avoid Hard-Coded Site URLs

Hard-coded URLs can break when:

  • Site friendly URL changes
  • Virtual host changes
  • Environment changes
  • Portal context changes
  • Application moves between development and production

Therefore:

Context-Aware URL > Hard-Coded URL

Custom Widget Support

Developers can also design custom Liferay applications to support Application Display Templates / Widget Templates where the relevant Liferay extension APIs are used. Conceptually:

Diagram
Custom Portlet
    |
    +--> Provides Data
    |
    +--> Registers Template Support
    |
    v
Widget Template
    |
    v
Custom Presentation

This provides administrators with presentation flexibility without requiring a new application deployment for every visual variation.

Custom Portlet Architecture

Suppose a custom application displays quantum assessments. Without templates:

Diagram
Quantum Assessment Portlet
       |
       v
Fixed JSP

With template support:

Diagram
Quantum Assessment Portlet
       |
       v
Assessment Entries
       |
       +----------------+
       |              |
       v              v
Card Template       Table Template
       |              |
       v              v
Card UI            Table UI

The same data can therefore support multiple presentations.

Example Quantum Assessment Template

Conceptually:

XML / HTML
<div class="row">

<#if entries?has_content>

    <#list entries as assessment>

       <div class="col-md-4 mb-3">

           <div class="card h-100">

              <div class="card-body">

                  <h3>
                     ${assessment}
                  </h3>

                  <p>
                     Quantum assessment
                  </p>

                  <button
                     class="btn btn-primary">

                     Start Assessment

                  </button>

              </div>

           </div>

       </div>

    </#list>

</#if>
XML / HTML
</div>

The exact assessment properties depend on the custom widget’s template context.

Widget Templates vs Fragments

Widget Templates and Fragments solve different problems.

CharacteristicWidget TemplateFragment
Primary purposeRender widget dataBuild page components
Data sourceWidget/applicationFragment context/configura-
Typical languageFreeMarkertion HTML/CSS/JavaScript/FreeMarker features
Relationship to widgetStrongUsually independent
Use caseAlternative widget displayPage composition
ExampleAsset cardsHero banner

Widget Template vs Fragment Example

Requirement:

“Display Asset Publisher news entries as cards.”

Use:

Widget Template

Requirement:

“Create a reusable hero section containing heading, image and button.”

Use:

Fragment

Widget Templates vs Themes

A Theme affects broad site presentation. A Widget Template affects a specific supported widget’s rendering. Conceptually:

Theme → Site-Level Presentation

while:

Widget Template → Widget-Level Presentation

Widget Template vs CSS Client Extension

CSS Client Extension:

Changes Styling

Widget Template:

Changes Markup/Rendering

For example, if the HTML is already correct but the color must change:

CSS

If:

XML / HTML
<ul>
  <li>...</li>
</ul>

must become:

XML / HTML
<div class="card">
...
</div>

then:

Widget Template

is more appropriate.

Widget Template vs Custom Element

A Widget Template renders data supplied by a Liferay widget. A Custom Element Client Extension is an independently developed frontend application.

Widget TemplateCustom Element
DataWidget-providedApplication-controlled
TechnologyFreeMarkerReact/Vue/Angular/JS
ComplexityLowerHigher
Use caseCustom renderingFull frontend application
RuntimeLiferay template renderingBrowser/external frontend

Decision Guide

A useful decision model is:

Diagram
Need UI customization?
       |
       +--> Existing Widget Data?
       |      |
       |       +--> Change Rendering?
       |             |
       |               +--> Widget Template
Diagram
|
+--> Reusable Page Component?
|      |
|       +--> Fragment
|
+--> Full React/Vue Application?
|      |
|       +--> Custom Element CX
|
+--> Styling Only?
       |
       +--> CSS / Theme CSS CX

Permissions

Widget Templates can have permissions governing who can:

  • View
  • Update
  • Delete
  • Manage

The exact actions depend on the Liferay version and resource. Templates containing important presentation logic should not be editable by unauthorized users.

Security Considerations

Template authors should consider:

  • Cross-site scripting
  • Dynamic output escaping
  • Unsafe HTML
  • Excessive service access
  • Sensitive data exposure
  • Permissions
  • User-generated content

A useful rule is:

Display Only What the User Is Authorized to See

Do Not Use Templates to Bypass Permissions

A Widget Template should not be treated as a mechanism for bypassing Liferay permissions. Correct architecture:

Diagram
User
 |
 v
Permission Check
 |
 v
Widget Data
 |
 v
Template
 |
 v
Display

not:

Diagram
Template
 |
 v
Retrieve Unauthorized Data

Performance Best Practices

A good Widget Template should:

  1. Keep logic simple.
  2. Avoid expensive operations inside loops.
  3. Avoid unnecessary service calls.
  4. Check for missing values.
  5. Avoid excessive nested loops.
  6. Render only necessary data.
  7. Use appropriate pagination at the widget/data layer.
  8. Avoid large amounts of inline JavaScript.

Separation of Responsibilities

A well-designed architecture is:

Diagram
Service Layer
    |
    | Retrieves Data
    v
Widget
Diagram
    |
    | Prepares Context
    v
Widget Template
    |
    | Renders
    v
HTML

Therefore:

Business Logic → Service
Presentation Logic → Template

Template Reusability

Suppose three pages use the same visual design:

Diagram
Page A -> Asset Publisher
Page B -> Asset Publisher
Page C -> Asset Publisher

Instead of implementing the card layout three times:

TA = TB = TC

use one shared template:

TCorporateCard

This improves maintainability.

Development Lifecycle

A practical development process is:

Diagram
Requirement
    |
    v
Choose Widget
    |
    v
Inspect Template Context
    |
    v
Create Widget Template
    |
    v
Write FreeMarker
    |
    v
Test with Real Data
Diagram
    |
    v
Check Permissions
    |
    v
Test Empty/Missing Values
    |
    v
Performance Test
    |
    v
Publish / Use

Testing Checklist

Test:

  • Zero entries
  • One entry
  • Many entries
  • Missing optional fields
  • Long titles
  • Special characters
  • Multiple languages
  • Guest user
  • Authenticated user
  • Mobile layout
  • Tablet layout
  • Desktop layout

Responsive Design

Templates should consider responsive layouts. For example:

XML / HTML
<div class="
    col-12
    col-md-6
    col-lg-4
">
    ...
</div>

Conceptually:

Mobile = 1 Card/Row
Tablet = 2 Cards/Row
Desktop = 3 Cards/Row

Accessibility

Custom templates should preserve accessibility. Consider:

  • Semantic HTML
  • Heading hierarchy
  • Alternative image text
  • Keyboard navigation
  • Accessible links
  • Button labels
  • Color contrast

For example:

XML / HTML
<img
    src="${imageURL}"
    alt="${imageAlt}"
/>

is preferable to an image with no meaningful alternative text.

Troubleshooting: Template Not Visible

Check:

  • Was the correct widget/application selected?
  • Was the template saved successfully?
  • Does the widget support Widget Templates?
  • Is the template available in the current site context?
  • Does the user have permission?

Troubleshooting: Invalid Reference

An error such as a missing FreeMarker variable may indicate that the template expects a variable not supplied by the widget. For example:

FreeMarker
${articleTitle}

when:

articleTitle ∈ / Context

Use the actual variables available to the template.

Troubleshooting: Template Works for Some Entries

If some entries render while others fail, check for optional fields. Bad:

FreeMarker
${entry.image.url}

when some entries have no image. Safer conceptually:

XML / HTML
<#if entry.image??>
    ...
</#if>

Troubleshooting: Slow Rendering

Check for:

  • Service calls inside loops
  • Deep nested loops
  • Too many entries
  • Large images
  • Excessive HTML
  • Expensive template operations

If:

RenderTime ∝ N × C

reduce either:

N

or:

C

Troubleshooting: Layout Looks Different

Check:

  • Theme CSS
  • Clay/Bootstrap classes
  • Custom CSS Client Extensions
  • Browser developer tools
  • CSS specificity
  • Responsive breakpoints

Remember:

Template HTML + Site CSS = Final Appearance

Practical Example Architecture

Suppose a portal has:

  • Liferay Objects storing Assessments
  • A widget retrieving Assessments
  • A Widget Template rendering cards
  • FastAPI performing quantum calculations

Architecture:

Diagram
+----------------------+
| Liferay Objects      |
| Assessment Data      |
+----------+-----------+
          |
          v
+----------------------+
| Assessment Widget    |
+----------+-----------+
          |
          v
+----------------------+
| Widget Template      |
| Card Presentation    |
+----------+-----------+
          |
          v
+----------------------+
| User                 |
+----------+-----------+
          |
          | Start
          v
+----------------------+
| FastAPI / Quantum    |
| Service              |
+----------------------+

The responsibilities remain clean:

Objects = Data
Widget = Application Logic
Template = Presentation
FastAPI = External Computation

Interview Questions and Answers

Multiple Choice Questions

Question 1

What is the main purpose of a Widget Template?

A. Change database schema

B. Customize widget presentation

C. Configure Elasticsearch

D. Create users

Answer: B

Question 2

Widget Templates were traditionally associated with which term?

A. ADT

B. OSGi

C. JDBC

D. JNDI

Answer: A

Question 3

Which template language is commonly used for Widget Templates?

A. SQL

B. FreeMarker

C. Java bytecode

D. YAML only

Answer: B

Question 4

Which FreeMarker construct performs iteration?

A. #list

B. SELECT

C. forEach() only

D. GROUP BY

Answer: A

Question 5

What should normally remain outside a Widget Template?

A. Presentation

B. HTML markup

C. Complex business logic

D. Conditional display

Answer: C

Question 6

Which is a classic application of Widget Templates?

A. Asset Publisher custom display

B. Database clustering

C. JVM heap tuning

D. DNS configuration

Answer: A

Question 7

Which is more appropriate for a reusable page hero component?

A. Fragment

B. Widget Template

C. Database trigger

D. Search index

Answer: A

Question 8

Which is more appropriate for rendering Asset Publisher entries as cards?

A. Widget Template

B. Database View

C. Cluster Link

D. OAuth Provider

Answer: A

Question 9

Why should service calls inside template loops be minimized?

A. They can create performance problems

B. FreeMarker cannot display HTML

C. They disable CSS

D. They delete entries

Answer: A

Question 10

Which expression conceptually checks whether a FreeMarker variable exists?

A. ??

B. DROP

C. JOIN

D. DELETE

Answer: A

Question 11

Which Client Extension is generally more suitable for a full React application?

A. Custom Element

B. Widget Template

C. Theme Favicon

D. Batch

Answer: A

Question 12

What does the Widget Template primarily receive?

A. Widget/application context and data

B. Database passwords

C. JVM bytecode

D. Search cluster credentials

Answer: A

Question 13

What should be done with optional values?

A. Assume they always exist

B. Check them or provide fallbacks

C. Delete the widget

D. Disable permissions

Answer: B

Question 14

What is the main security concern when rendering untrusted dynamic content?

A. XSS

B. Database replication

C. JVM garbage collection

D. DNS caching

Answer: A

Question 15

Which statement best describes good template design?

A. Put all application logic in FreeMarker

B. Keep presentation in the template and business logic in the application/service layer

C. Access the database directly from every loop

D. Hard-code all URLs

Answer: B

Quick Revision Table

ConceptMeaning
Widget TemplateAlternative presentation for a supported widget
ADTApplication Display Template
FreeMarkerCommon Liferay template language
Template ContextVariables and objects available to a template
#listFreeMarker iteration
#ifConditional rendering
??Checks whether a value exists
Default ValueFallback when a value is absent
Asset PublisherClassic Widget Template use case
FragmentReusable page-building component
Custom ElementIndependent frontend application integration
ThemeSite-wide presentation mechanism
CSS Client ExtensionExternal/custom styling mechanism
LocalizationRender text according to current locale
EscapingProtect output from unsafe dynamic content
N+1 ProblemRepeated expensive calls while rendering a collection

Complete Architecture

A practical Liferay presentation architecture can be visualized as:

Diagram
   LIFERAY DATA
       |
       v
+---------------+
| Service Layer |
+-------+-------+
       |
       v
+---------------+
|    Widget     |
+-------+-------+
       |
       | Template Context
       v
+---------------+
| Widget        |
| Template      |
| FreeMarker    |
+-------+-------+
       |
       | HTML
       v
+---------------+
| Browser       |
+---------------+

The division of responsibility is:

Data → Service
Application Behavior → Widget
Presentation → WidgetT emplate
Final Rendering → Browser

Key Takeaway

The simplest way to remember Widget Templates is:

Same Widget + Same Data + Different Template = Different Presentation

For example:

AssetPublisher + T1 = List
AssetPublisher + T2 = Cards
AssetPublisher + T3 = Grid

without changing the underlying Asset Publisher business logic.

A good Liferay architecture therefore follows:

Business Logic̸ = Presentation Logic

with:

Business Logic → Portlet / Service Layer

and:

Presentation Logic → Widget Template

Use a Widget Template when an existing widget already supplies the correct data and behavior but its presentation needs to change.

Version Considerations

Liferay 7.4 spans many GA and quarterly releases. Before implementing a production Widget Template, verify:

  • Exact Liferay DXP/Portal release
  • Whether the target widget supports Widget Templates
  • Available template context variables
  • Supported FreeMarker capabilities
  • Security restrictions
  • Available frontend/Clay classes
  • Site permissions

The template context supplied by the target widget should be treated as the authoritative source for the variables and objects that the template can use.

Official Reference

For exact configuration and release-specific details, consult Liferay’s official documentation for creating Widget Templates.

Prefer to read offline? Download the PDF edition (34 pages).