ACA Blog

ACA Blog

April 2020
« Mar    


Creating custom DDM field types in Liferay 7.x

Peter MesottenPeter Mesotten

Extending the DDM modules in Liferay with custom field types isn’t that easy. This blog post is the result of our attempts to do it. The first part recaps what DDM actually means and where you use it. After that, we show you an example of a flexible custom DDM field type that we created. Finally, the last part of this blog gives you some pointers on how to create custom DDM field types on your own.

DDM… what’s DDM?

DDM stands for Dynamic Data Mapping, a set of modules that defines various types of fields used to assemble:

Liferay bundles with an ever-expanding set of out-of-the-box DDM field types. At the moment of speaking (Liferay 7.1 has just released), the following field types are available:

Field type Field appearance Available for use in
WCM structures Data definitions Metadata sets
Boolean Checkbox field X X X
Color Color picker X X X
Date Date picker X X X
Decimal Input field that validates that the input is a decimal X X X
Documents and Media Documents and Media selector X X X
Geolocation Marker on a map X X X
HTML Rich text field (AlloyEditor) X X X
Image Button to upload local image or select image from Documents and Media X
Integer Input field that validates that the input is an integer X X X
Link to Page Selector for a public or private page within the current site X X X
Number Input field that validates that the input is a decimal or an integer X X X
Radio List of radio buttons with preconfigured options X X X
Select Drop-down field (single selection) or listbox field (multi-selection) with preconfigured options X X X
Separator Horizontal line X
Text Single-line text field X X X
Text Box Multi-line text field X X X
Web Content Web content article selector X X X

Is it ever enough?

For basic content management needs, the default set of DDM field types usually suffices. However, there certainly are use cases which require you to create custom field types:

In this article, we will examine how to create such custom fields. As an example, we’ll pick the first use case and try to create a field type which takes the response of a REST endpoint as the possible values of a dropdown list.

A new field type was born: REST Select

The default Select field in Liferay allows content authors to pick a value from a predefined list of possible values for an article. This is great for simple purposes, but what if you want to dynamically populate this drop-down list with values from an external platform? Or if the listed values depend on the user that requests them?

Meet the brand new REST Select field. This dropdown field allows you to configure a REST endpoint and map the JSON fields in the response onto the labels and values of the possible options.

Install the module

Perform the following actions to install the module in your Liferay installation:

  1. Clone and check out the 7.x/field/ddm-rest-select branch.
  2. Build the project using Maven by executing mvn clean package.
  3. Move the resulting JAR (you can find it in the target folder) into the deploy folder of Liferay.

Define the field in a structure

  1. Create a new web content structure.
    (Note that you can also create a dynamic data definition or a metadata set instead. For testing purposes, though, it is easier to start with the familiar web content structure.)
  2. Drag the “REST Select” field type into the structure definition.
    Custom ddm field - step 2
  3. Configure the field’s endpoint and option mappings by selecting the field.
    Custom ddm field - step 3

Apart from the default attributes like “Field Label” and “Required”, notice there are 3 additional attributes that you need to configure. You should fill the first attribute with the URL of a REST endpoint. This should be an endpoint that returns a list of JSON objects. E.g. the endpoint http://localhost:8080/api/jsonws/country/get-countries (a built-in endpoint in Liferay) returns the following output:

With the two remaining attributes, you configure what should be respectively in the label and the value of the HTML <option> elements. E.g. in this case, if you pick the “nameCurrentValue” JSON attribute for the option label and the “a3” JSON attribute for the option value, this will produce the following HTML:

    <option value="AFG">Afghanistan</option>
    <option value="ALA">Aland Islands</option>

Create a new article using the structure

When creating a new web content article based on the structure you’ve just created, you’re able to select a country from the dynamically loaded dropdown list!

Cool, now I want to create my own custom DDM field type! So… how?

In this part of the blog, we explore how Liferay was extended to support the new REST Select field. Hopefully, this gives you enough insights to start working on your own custom DDM field type!


It turned out to be quite a journey to create new DDM fields in Liferay, even in 7.x. You would expect that every field type is defined in its own OSGi module, but the woeful truth is that the definition and rendering of these fields is scattered throughout several Liferay modules in both client-side and server-side code. So the result is rather hacky to say the least.

Please only consider this solution if there is absolutely no other way!!

With that being said, do go on reading this article (wink)

The code

The starting point is This repository provides a skeleton project that can be extended to support new DDM field types. Each part that needs to be extended or implemented is marked with a //TODO comment. You can do a diff of this main branch with the 7.x/field/ddm-rest-select branch to see the different changes to provide your own implementation.



While it was a real challenge to create a custom DDM field, it IS possible. If you inject enough flexibility in your field, it can even serve multiple purposes. Please send me your feedback on how you would do things differently or what field types you are missing at the moment in Liferay 7.x.

Thanks for reading!


Looking for more useful content on Liferay? Check out our other blog posts or take a look at the Liferay community blogs!

newest oldest most voted
Notify of
Muhammad Usman
Muhammad Usman

Hi Peter,
i followed your tutorial but when i deploy it in liferay and check the status in Gogo shell, its stuck on installed. when i starts it through Gogo shell it gives an error
org.osgi.framework.BundleException: Could not resolve module: [973]
Unresolved requirement: Import-Package:
any clue?


Hi, great tutorial and code. I need some advice though. Based on your code I created a simple new field for LR7.0: it is just a div with a title, a paragraph (no input elements for this field). In the ftl template of this field I added the variable ${fieldStructure.children} to show also nested fields. Unfortunately when I save the corresponding web content the nested fields are not saved. Any clue on how this issue can be solved?


Just solved: the ${fieldStructure.children} must be put directly under the taglib.


Another question: I added the “repeatable” option to the field; when I fill the web content and press the “+” button to repeat the field and all the nested ones, the field and its children is drawn, the ‘plus’ and ‘minus’ icons do not appear and in console the browser says “TypeError: fieldInstanceId is undefined”. If I save this web content only the first block of field is saved and not the repeated ones. Any toughts to share?

Sandro Zacchino
Sandro Zacchino

also this step was solved. In the ftl everything must be enclosed within the field-wrapper taglib.

Aadil Mansuri
Aadil Mansuri

Hi Peter,
I followed your tutorial but when I added “daterangepicker” all code going good but when I try to drop “daterangepicker” its through an error TypeError: n.getFieldClass(…) is not a constructor
at component.createField (:8080/combo/?
at Y.Subscriber._notify (everything.jsp:52970)
at Y.Subscriber.notify (everything.jsp:52999)
at Y.CustomEvent._notify (everything.jsp:52662)
at Y.CustomEvent._procSubs (everything.jsp:52788)
at Y.CustomEvent.CEProto.fireComplex (everything.jsp:54336)
at Y.CustomEvent._fire (everything.jsp:52735)

how i manage it?