• Liferay Search Container Sorting

    Posted on October 4, 2014 by Hamidul Islam in Liferay.

    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 sortedThe 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

    Post Tagged with ,

10 Responses so far.

  1. dhanush says:

    it really helpful for me thanks for this blog

  2. Chirag says:

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

  3. Varshika says:

    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.

  4. rasul says:

    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.

  5. Banafshe says:

    It's really helpful for me thank you.
    It needs to add "commons-beanutils.jar" and "commons-collections.jar" jars on the build path.

  6. chivas says:

    why I follow your instructions but can not click my header col?

    • scrooge9 says:

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

  7. roy says:

    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

  8. paul says:

    "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

Your email address will not be published. Required fields are marked *

Are you human? * Time limit is exhausted. Please reload CAPTCHA.

Top
%d bloggers like this:

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close