Simple AEM Granite Order Widget (Draggable List) | AEM Community Blog Seeding


Community Manager



Simple AEM Granite Order Widget (Draggable List) by Ahmed Musallam


Recently, we had the need for an authoring experience where, an author can re-order a list of fixed tabs to their desired order. The only Granite widget that allows drag-n-drop ordering is the multifield, but we don’t need a multifield, we just wanted the ability to order a fixed list.

An Existing solution
ACS Commons has this Draggable Lists Widget but I did not want to include ACS commons just for that widget. Additionally, I looked at the implementation for that widget and it seemed to be complex granted it might be solving a different problem. It also used Coral UI 2; we are on AEM 6.4 where Coral UI 3 is the latest Coral version.

A Simple Solution
If you look at Coral UI 3 documentation, the only component that allows drag-n-drop ordering is the Coral.Table component. Which means, we can create a Granite widget that uses that UI to render a list!

Here is the widget JSP impl: (Java 8)

for the purpose of this post, I’ve created /apps/widgets/orderedList/orderedList.jsp

Here, I render each item in the list as a hidden field with the same “name”.

The order of the hidden fields in the HTML is what determines the saved order in the JCR content node/prop.

This also means that we dont need ANY custom JS to make this work! just the OOTB CUI3 Table component!

Renders a List of items for ordering purposes only
%><%@ include file="/libs/granite/ui/global.jsp" %><%
%><%@ page session="false"
java.util.*" %>
Ordered List
.. granite:servercomponent:: widgets/orderedList
Renders a List of items for ordering purposes only

It has the following content structure:
+ myList
- sling:resourceType = "widgets/orderedList"
- name = "./myList"
- title = "My List"
+ items
+ item1
- text = "Item 1"
- value = "item1"
+ item 2
- text = "Item 2"
- value = "item2"
if (!cmp.getRenderCondition(resource, false).check()) {
Tag tag = cmp.consumeTag();
AttrBuilder attrs = tag.getAttrs();
Config cfg = cmp.getConfig();
String title = cfg.get("title", String.class);
String name = cfg.get("name", String.class);

// the easy way to do this...
String cleanName =
name != null
? name.replace(".", "").replace("/", "")
: "";
String tableId = "order-table-" + cleanName;
String hiddenInputId = "order-input-" + cleanName;
String[] values = cmp.getValue().getContentValue(name, new String[0]);
List valuesList = Arrays.asList(values);
Iterator itemsIterator = cmp.getItemDataSource().iterator();

// server-side ordering of values based on already saved order
List items = StreamSupport.stream(
Spliterators.spliteratorUnknownSize(itemsIterator, Spliterator.ORDERED),
Comparator.comparing(item -> {
ValueMap vm = ((Resource) item).getValueMap();
String val = vm.get("value", "");
return valuesList != null ? valuesList.indexOf(val) : 0;
> <% for (ValueMap vm : items) { %> <% } %>
<%=vm.get("text", "") %> "/>  

Read Full Blog

Simple AEM Granite Order Widget (Draggable List)


Please use this thread to ask the related questions.

AEM AEMEBlogSeeding Experience Manager