How to allow end user sorting a list
Question
If you want to allow an end user to sort a list, then you should build a query on your list.
In this basic example, we will show how to allow the end user to sort a list using the title of each list item, or the publication date of each item. We will also allow the end user to choose the sort order.
Answer
First, imagine this very simple definition:
[jnt:myDocumentList] > jnt:contentList, jmix:droppableContent, mix:title
+ * (jnt:myDocument)
[jnt:myDocument] > jnt:content, mix:title
It declares a jnt:myDocumentList
list of jnt:myDocument
items. Each item have a mix:title
, meaning that it will declare a jcr:title
property
First, we will prepare both list and content views.
Here is the list view for jnt:myDocumentList. We simply iterate on all items of the list and relaying the content view of all children. We also allow the editor to add jnt:myDocument items in the list
jnt_myDocumentList/html/myDocumentList.jsp
<%@ page language="java" contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="template" uri="http://www.jahia.org/tags/templateLib" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<template:include view="hidden.header"/>
<h1>${currentNode.displayableName}</h1>
<c:forEach items="${moduleMap.currentList}" var="subchild" begin="${moduleMap.begin}" end="${moduleMap.end}">
<template:module node="${subchild}" editable="${moduleMap.editable && !resourceReadOnly}"/>
</c:forEach>
<c:if test="${renderContext.editMode}">
<template:module path="*" nodeTypes="jnt:myDocument"/>
</c:if>
As you can see, on the top of this file we use the <template:include view="hidden.header"/>
. This hidden.header calls a "loader" whose role is to get all nodes to display and store them in ${moduleMap}
And here is the very minimalist view of the content: jnt_myDocument/html/myDocument.jsp
<%@ page language="java" contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%--@elvariable id="currentNode" type="org.jahia.services.content.JCRNodeWrapper"--%>
<h2>${currentNode.properties['jcr:title'].string}</h2>
<p><fmt:formatDate type="both" dateStyle="medium" timeStyle="medium"
value="${currentNode.properties['j:lastPublished'].time}"/></p>
At this time of the development, there is no way for the end user to sort the list. The idea here is to generate URLs with parameters to send the nodeType (it will be the j:lastPublished
or the jcr:title
) we want to sort on, and also the sort order (it will be asc
or desc
).
To do it, we create 4 dedicated links in the list view:
<c:url var="publishedAscUrl" value="${renderContext.mainResource.node.url}">
<c:param name="nodeType" value="j:lastPublished"/>
<c:param name="sortOrder" value="asc"/>
</c:url>
<c:url var="publishedDescUrl" value="${renderContext.mainResource.node.url}">
<c:param name="nodeType" value="j:lastPublished"/>
<c:param name="sortOrder" value="desc"/>
</c:url>
<c:url var="titleAscUrl" value="${renderContext.mainResource.node.url}">
<c:param name="nodeType" value="jcr:title"/>
<c:param name="sortOrder" value="asc"/>
</c:url>
<c:url var="titleDescUrl" value="${renderContext.mainResource.node.url}">
<c:param name="nodeType" value="jcr:title"/>
<c:param name="sortOrder" value="desc"/>
</c:url>
Sort by published date <a href="${publishedAscUrl}">asc</a> | <a href="${publishedDescUrl}">desc</a><br/>
Sort by title <a href="${titleAscUrl}">asc</a> | <a href="${titleDescUrl}">desc</a><br/>
And as the output of the list will be different depending on the value of each parameter, we will need to deal with the cache. To do it we will create a property file for the list
jnt_myDocumentList/html/myDocumentList.properties
cache.requestParameters=sortOrder,nodeType
And now we can create our query in a jnt_myDocumentList/html/myDocumentList.hidden.load.jsp
First, we get the parameters, and if we have values for both nodeType
and sortOrder
then we create a query definition and we set it to our moduleMap
We limit the query to the nodes of the list and to the type jnt:myDocument
<%@ page language="java" contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="query" uri="http://www.jahia.org/tags/queryLib" %>
<%--@elvariable id="currentNode" type="org.jahia.services.content.JCRNodeWrapper"--%>
<c:set var="nodeType" value="${param.nodeType}"/>
<c:set var="sortOrder" value="${param.sortOrder}"/>
<c:if test="${! empty nodeType && ! empty sortOrder}">
Let's build the query sorted by ${nodeType} - ${sortOrder}
<query:definition var="listQuery">
<query:selector nodeTypeName="jnt:myDocument"/>
<query:descendantNode path="${currentNode.path}"/>
<query:sortBy propertyName="${nodeType}" order="${sortOrder}"/>
</query:definition>
<c:set target="${moduleMap}" property="listQuery" value="${listQuery}"/>
</c:if>
And that's all. Now we have a user sortable list. Here would be the result: