Liferay Search Container Sorting

Search Container Sorting

aimLiferay Search Container is the great way to display your data in a grid format with nice pagination. One beauty of search container is that it’s very flexible and configurable. Do you want to sort one or more header columns? Then this is the article for you. It explains the nut and bolts to sort liferay search container headers.

 7 Points for sortable column

1.  What makes a Liferay Search Container Column sortable?

An attribute orderable=”true” to liferay-ui:search-container-column-text

2.  How to define sorting order asc or desc?

An attribute orderByType=”asc” or orderByType=”desc”  to liferay-ui:search-container tag.

3.  What API should I use to sort columns?

org.apache.commons.beanutils.BeanComparator is the API that we can use to sort a specific column.

4.  Do I need to download JAR for Apache Bean Comparator?

No. Liferay already has this JAR. Just need to use it. 

5. What about custom comparator? Do I need it?

Yes and No. org.apache.commons.beanutils.BeanComparator  can be used to sort any columns. However custom comparator can also be used. In this article custom comparator is not used.

6. Where should I write the sorting logic?

The sorting logic is too small. The sorting logic can be written both in JSP as well as in Portlet class. In this article the logic for sorting is explained in JSP.

7. What happens when a column header is sorted?

When a column header is clicked for sorting some parameters are passed in request scope. Two parameters orderByCol and orderByType are responsible sorting. orderByCol parameter says which column need to be sorted and orderByType parameter says in which order the column should be sorted. The value of orderByType should be either asc or desc.

JSP Code:


<%@page import="java.util.Collections"%>
<%@page import="org.apache.commons.beanutils.BeanComparator"%>
<%@page import="java.util.ArrayList"%>
<%@page import="com.liferay.portal.kernel.util.ListUtil"%>
<%@page import="com.liferay.portal.kernel.dao.orm.QueryUtil"%>
<%@page import="com.liferay.portal.service.UserLocalServiceUtil"%>
<%@page import="com.liferay.portal.model.User"%>
<%@page import="com.liferay.portal.kernel.util.ParamUtil"%>
<%@page import="com.liferay.portal.kernel.util.Validator"%>
<%@page import="java.util.List"%>

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
<%@ taglib uri="http://liferay.com/tld/theme" prefix="theme"%>
<%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
<portlet:defineObjects />
<theme:defineObjects />

<%
//orderByCol is the column name passed in the request while sorting
String orderByCol = ParamUtil.getString(request, "orderByCol"); 

//orderByType is passed in the request while sorting. It can be either asc or desc
String orderByType = ParamUtil.getString(request, "orderByType");
String sortingOrder = orderByType;
//Logic for toggle asc and desc
if(orderByType.equals("desc")){
    orderByType = "asc";
}else{
    orderByType = "desc";
}

if(Validator.isNull(orderByType)){
    orderByType = "desc";
}

%>
<liferay-ui:search-container  orderByType="<%=orderByType %>"  >

<liferay-ui:search-container-results >
    <%
    //Get all the users from User_ table
     List<User> allUsers = UserLocalServiceUtil.getUsers(QueryUtil.ALL_POS,QueryUtil.ALL_POS);
    //usersPerPage is unmodifyable list. It can not be sorted.
    List<User> usersPerPage = ListUtil.subList(allUsers, searchContainer.getStart(),searchContainer.getEnd());
    int totalUsers =  UserLocalServiceUtil.getUsersCount() ;
    
    //From usersPerPage a new list sortableUsers is created. For sorting we will use this list
    List<User> sortableUsers = new ArrayList<User>(usersPerPage);
    if(Validator.isNotNull(orderByCol)){
        //Pass the column name to BeanComparator to get comparator object
        BeanComparator comparator = new BeanComparator(orderByCol);
        if(sortingOrder.equalsIgnoreCase("asc")){
            
            //It will sort in ascending order
            Collections.sort(sortableUsers, comparator);
        }else{
            //It will sort in descending order
            Collections.reverse(sortableUsers);
        }

    }

    //sortableUsers list is sorted on the basis of condition. When page load it wont be sorted
    //It will be sorted only when a header of coulmn is clicked for sorting
    pageContext.setAttribute("results", sortableUsers);
    pageContext.setAttribute("total", totalUsers);
    %>
</liferay-ui:search-container-results>

    <liferay-ui:search-container-row
        className="com.liferay.portal.model.User"
        modelVar="aUser"
    >
    
        <!-- orderableProperty="userId" this means that when this column is sorted orderByCol=userId is passed in the request-->
        <!-- if orderableProperty attribute is not mentioned then orderByCol=User Id is passed in request parameter at the time of sorting -->
        <!--orderable="true" means this column is sortable -->
        <!--Using name="User Id" we are saying that header should be User Id. If its not mentioned the header would be userId -->
        <liferay-ui:search-container-column-text  property="userId" orderable="true" name="User Id" orderableProperty="userId" />

        <liferay-ui:search-container-column-text property="status" orderable="true" />

        <liferay-ui:search-container-column-text property="firstName" orderable="true" name="First Name" orderableProperty="firstName"/>

        <liferay-ui:search-container-column-text property="female" orderable="true" />

        <liferay-ui:search-container-column-text property="emailAddress" orderable="true" name="Email Address" orderableProperty="emailAddress"/>

        <liferay-ui:search-container-column-text property="lastName" orderable="true" name="Last Name" orderableProperty="lastName"/>

        
    </liferay-ui:search-container-row>

    <liferay-ui:search-iterator />
</liferay-ui:search-container>

Note 1: Please read the code comments for clear understanding of the code.

Note 2: The default functionality of search container should pass toggle asc or desc order type at the of sorting. But it is not happening.May be it is a bug. So custom toggle code is written.

Note 3:

List<User> usersPerPage = ListUtil.subList(allUsers, searchContainer.getStart(),searchContainer.getEnd());

is unmodifiable list. You can not sort it. Just create another list from it to make it modifiable.

Note 4: By default org.apache.commons.beanutils.BeanComparator is not available in plugin portlet. However you can make it available by including portal dependency in liferay-plugin-package.properties.

Portal Dependency

Sample Screen Shot:

Sortable Search Container

About The Author

10 thoughts on “Liferay Search Container Sorting”

  1. its really good and help full,
    I have one doubts can we do same thing using server side coding??

  2. Its really helpful.i have followed this and created a sorting for my custom users list portlet. In that i am displaying columns like first name, last name, Organization. Using this code, am able to sort based on first name, but i want to sort the users based on their Organization name also. i am displaying Organization values using expando. here in search container, we are spcifying model class as className=”com.liferay.portal.model.User” . how can i implement sort for Organization? Please guide me.

    Thanks.

  3. Thank you very much.

    But to let it work properly, i had to change some lines as follows:

    if(Validator.isNotNull(orderByCol)){
    //Pass the column name to BeanComparator to get comparator object
    BeanComparator comparator = new BeanComparator(orderByCol);
    //It will sort in ascending order
    Collections.sort(sortableUsers, comparator);
    if(sortingOrder.equalsIgnoreCase("asc")){

    }else{
    //It will sort in descending order
    Collections.reverse(sortableUsers);
    }

    }

    sortableUsers array was not pre-sorted.. So i had to sort it first, then take its reverse.

  4. It’s really helpful for me thank you.
    It needs to add “commons-beanutils.jar” and “commons-collections.jar” jars on the build path.

    1. Next to <liferay-ui:search-container-column-text add this orderable="true" to make the header clickable

  5. I tried implementing the code above the but if I get it to work in ascending, I cannot make work in descending. Can anyone tell the work around for my issue. Thanks

  6. “Note 2: The default functionality of search container should pass toggle asc or desc order type at the of sorting. But it is not happening.May be it is a bug. So custom toggle code is written.” – You need to set “orderByCol” param in “searchContainer” tag for it to work 🙂

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top