Liferay Objects FreeMarker Display Widget

Liferay Objects equivalent of the DDL ‘Display Template’ feature to fill a gap in DDL to Objects migration

Introduction

The Liferay Dynamic Data Lists (DDL) functionality is now deprecated and marked for removal, with Liferay Objects the replacement for DDL.

For customers migrating existing DDL Lists to Liferay Objects, where the customer used the DDL 'Display Template' functionality to display a collection of DDL Records, this OSGi Liferay MVC widget is intended as an alternative for use with Liferay Objects and FreeMarker.

Existing DDL 'Display Templates' can be updated to be compatible with the widget for reuse with Liferay Objects once the data has been migrated into Liferay Objects.

The widget source code is available here with sample templates, object definitions and a full README containing setup instructions.

Some sample screenshots:


 


 

Alternative Template Types?

Liferay Objects records can be used with various FreeMarker Template types:

- A 'Display Page Template' can be used to view a single record in it's own page. It is not a like for like replacement for DDL Display Templates.

- An 'Information Template' is applied to each record in the collection. "Information templates can be used with collection items, but they apply to each item individually, so you can’t style the entire collection with a single template." As such it is not a like for like replacement for DDL Display Templates.

- Although an 'Asset Publisher Widget Template' is applied to the collection, the Asset Publisher widget is now in Maintenance Mode so is not a recommended alternative.

There isn't a direct replacement for the DDL Display Template functionality with Liferay Objects to display a list of Liferay Object records with a single FreeMarker Template. This widget aims to fill that gap.

Flexible Data Source

The widget can retrieve records in the FreeMarker template using:

- Liferay Object Headless APIs in JSON format:

Use the OOTB restClient.get(...).items method to retrieve records via the Liferay Object Headless APIs. See here for more details on the restClient e.g.

restClient.get("/c/students/?nestedFields=studentAttachments&page=1&pageSize=-1&sort=studentName:asc").items

OR 

- List of Java com.liferay.object.model.ObjectEntry records:

Use the custom helper classes to retrieve the records e.g.

objectEntryHelper.getRecords("studentName", true, objectDefinition, locale, themeDisplay.siteGroup)

restClient.get(...).items vs ObjectEntry records

- The decision on which approach to use can be based on which the team is more comfortable working with or on the specific use case and data structure etc.

- The restClient.get(...).items approach involves a single call to get the object records and the related records e.g. students and the studentAttachments.

- The com.liferay.object.model.ObjectEntry approach is potentially less efficient as it get the Object records, then for each Object Record it gets it's related records where applicable.

- Depending on the use case the restClient.get(...).items approach MAY be more efficient.

- One or other can be used for each specific use case, as needed.

Highly Configurable

The widget is configuration driven with portable configuration:

- TemplateObjectDefinition Object to store FreeMarker Templates.

- Widget Configuration to map to TemplateObjectDefinition Record and Object Definition.

- An Object Definition can be used with different FreeMarker Templates e.g. Student List and Student Table.

- User Defined External Reference Codes (ERCs) used to map configuration.

- Widget Configuration is Portable for Staging usage.

Additional Widget Features

- Display records for an Object using a FreeMarker Template: Widget can be used on Content Pages and Widget Pages. Widget is Instanceable meaning it can be included multiple times on the same page.

- Permission Aware Objects Records: Renders Object Records for Authenticated and Guest users based on Object Record permissions. For both ‘main’ Object Record permissions and ‘related’ Object Record permissions.

- Object Scope: Works with both Company and Site Scoped Objects

- Localization Aware: Driven by 'Enable Entry Translation' on Object Definition. Does not require Liferay Objects to be Translation enabled, even if the Virtual Instance has multiple Languages enabled.

ObjectEntry Custom Helper Classes

Custom helper classes are provided in the FreeMarker context for use when working with com.liferay.object.model.ObjectEntry records as follows:

- AttachmentFieldHelper for rendering File Links e.g. with Label and Size

<#assign attachment = attachmentFieldHelper.getAttachmentURL(themeDisplay, cur_attachment.values.file)>

- ObjectEntryHelper for retrieving the records with default sort etc.

<#assign records = objectEntryHelper.getRecords("studentName", true, objectDefinition, locale, themeDisplay.siteGroup)>

- PicklistHelper for working with Picklists

<#assign skills = picklistHelper.getEntryNamesList(picklist_skills, cur_rec.values["skills"], languageId)>

- RelationshipHelper for working with Relationships (One to Many only currently)

<#assign attachments = relationshipHelper.getRecordsSorted(relationship_studentAttachments, cur_rec.objectEntryId, languageId)>

Known Limitations / TODO

- The com.liferay.object.model.ObjectEntry implementation doesn't currently handle Many to Many relationships. Additional methods can be added to RelationshipHelper.java to support Many to Many relationships if required.

- Further improvements can be made e.g. to add support for composite sort to ObjectEntryHelper getRecords method.

- Additional Helper classes can easily be added for reusable code to further reduce the complexity of the FreeMarker templates.

- The DDL 'Display Templates' feature was not intended for displaying large quantities of data, the same applies to this widget.

- Adding pagination support to the widget should be possible if the Liferay Object has many records.

Blogs