Expand my Community achievements bar.

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

Avatar

Administrator

BlogImage.jpg

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

Abstract

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"
import="java.util.Iterator,
com.adobe.granite.ui.components.AttrBuilder,
com.adobe.granite.ui.components.Tag,
com.adobe.granite.ui.components.Config,
org.apache.sling.api.resource.ValueMap,
java.util.stream.StreamSupport,
java.util.stream.Collectors,
java.util.*" %>
<%--###
Ordered List
====
// TODO
.. 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()) {
return;
}
Tag tag = cmp.consumeTag();
AttrBuilder attrs = tag.getAttrs();
attrs.addClass("coral-Well");
cmp.populateCommonAttrs(attrs);
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),
false
).sorted(
Comparator.comparing(item -> {
ValueMap vm = ((Resource) item).getValueMap();
String val = vm.get("value", "");
return valuesList != null ? valuesList.indexOf(val) : 0;
})
).map(Resource::getValueMap)
.collect(Collectors.toList());
%>
> <% for (ValueMap vm : items) { %> <% } %>
<%=title%>  
<%=vm.get("text", "") %> "/>  
 

Read Full Blog

Simple AEM Granite Order Widget (Draggable List)

Q&A

Please use this thread to ask the related questions.



Kautuk Sahni
Topics

Topics help categorize Community content and increase your ability to discover relevant content.

0 Replies