You are here

Using pagination in the WebCenter Content Presenter

A lot has been written about the content presenter and many people say it is a very powerful tool to integrate content from WebCenter Content into your portal. I fully agree with this but sometimes the content presenter lacks functionality that you would think would be out of the box.

One of those functionalities is having pagination when you have a lot of items to display. Suppose that you want to display the contents of a folder or the result of a query and the number of results can be very large, how will you display this in a proper way to your users? Simple, use pagination! But the content presenter does not support this so we will have to build it ourselves.

In this post I will explain how we can create pagination for the content presenter by building a custom content presenter template.

You can download the example application from here.

It requires only a few steps:

  • Create a managed bean to handle the pagination
  • Create the content presenter template
  • Add the content presenter
  • Enjoy

I've been thinking on a way of doing this without using a managed bean because this would be easier when you want to use the template in WebCenter Spaces. Unfortunately, I don't think this is possible... If someone can think of a way to replace the functionality of the managed bean by putting it in the template, please let me know!

The managed bean will handle the action for the Next and Previous button. It will also check if there is a next or previous page so we can disable the buttons accordingly. In order to do so, we need to keep track of the currentPage and pageSize. Based upon those two attributes we can make our calculations.

Here's the handler for the next button:

  1. public void nextPage(ActionEvent e){
  2.  currentPage++;
  3.  if(currentPage*pageSize >= citerator.getRowCount()){
  4.     cmdNext.setDisabled(true);
  5.     AdfFacesContext.getCurrentInstance().addPartialTarget(cmdNext);
  6.  }
  7.  cmdPrev.setDisabled(false);
  8.  AdfFacesContext.getCurrentInstance().addPartialTarget(cmdPrev);
  9. }

The code is quite straight forward. We set the currentPage to its new value and we check if the next page button should be disabled or not.

The same logic applies to the previousButton:

  1. public void previousPage(ActionEvent e){
  2.     currentPage--;
  3.     if(currentPage == 1){
  4.         cmdPrev.setDisabled(true);
  5.        AdfFacesContext.getCurrentInstance().addPartialTarget(cmdPrev);
  6.     }
  7.    cmdNext.setDisabled(false);
  8.   AdfFacesContext.getCurrentInstance().addPartialTarget(cmdNext);
  9. }

In this case the check is easier because we only need to disable the previous page if we are on the first page.

Another piece of code to notice is the getFirst method:

  1. public int getFirst(){
  2.   return pageSize*(currentPage-1);
  3. }

This will be used to drive the pagination to the iterator. In our template, the af:iterator has a first attribute which tells the iterator which index is the first one to show.

These are the most important parts of the code.

The next step is to create the content template. Here's the code from the example application:

  1. <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
  2.          xmlns:dt="http://xmlns.oracle.com/webcenter/content/templates"
  3.          xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
  4.          xmlns:f="http://java.sun.com/jsf/core">
  5.   <dt:contentListTemplateDef var="nodes">
  6.     <af:panelGroupLayout id="pnlContainer" layout="vertical"
  7.                         partialTriggers="cmdPrev cmdNext">
  8.     <af:iterator id="pagList" value="#{nodes}" var="node"
  9.          first="#{paginationBean.first}" rows="#{paginationBean.pageSize}"
  10.                 binding="#{paginationBean.citerator}">
  11.         <af:panelGroupLayout id="pnlContent" layout="vertical">
  12.             <dt:contentTemplate node="#{node}"  id="content"
  13.              view="oracle.webcenter.content.templates.default.list.item"/>
  14.         </af:panelGroupLayout>
  15.     </af:iterator>
  16.     </af:panelGroupLayout>
  17.     <af:spacer id="sp2" height="10px"/>
  18.     <af:panelGroupLayout id="pnlPag" layout="horizontal">
  19.         <af:commandLink text="Previous" id="cmdPrev"
  20.            disabled="#{paginationBean.currentPage eq 1}"
  21.            actionListener="#{paginationBean.previousPage}"
  22.            partialTriggers="cmdNext" partialSubmit="true"
  23.                        binding="#{paginationBean.cmdPrev}"/>
  24.          <af:commandLink text="Next" id="cmdNext"  
  25.         disabled="#{paginationBean.currentPage * paginationBean.pageSize ge paginationBean.citerator.rowCount}"
  26.          partialTriggers="cmdPrev" actionListener="#{paginationBean.nextPage}" partialSubmit="true"
  27.            binding="#{paginationBean.cmdNext}"/>
  28.       <f:facet name="separator"><af:spacer id="sp1" width="5px"/></f:facet>
  29.     </af:panelGroupLayout>
  30.   </dt:contentListTemplateDef>
  31. </jsp:root>

Most of the code is layout. One of the most important parts is the definition of the iterator:

  1. <af:iterator id="pagList" value="#{nodes}" var="node"
  2.          first="#{paginationBean.first}" rows="#{paginationBean.pageSize}"
  3.          binding="#{paginationBean.citerator}">

As told previously, the first attribute will calculate the actual starting element. The rows attribute will tell the iterator how many rows it should display. Because we need to know this, we have created the attribute in our managed bean and bound this to the iterator.

I also bound the iterator to an object in my managed bean. This is because I need to know how many elements the iterators holds in order to know when to disable to next page button.

There is also a panelGroupLayout surrounding the iterator. This is required because we need to have a component with the partialTriggers attribute. The af:iterator does not support this attribute so we surround it with the panelGroupLayout. This group will be refreshed whenever we click on the Previous or Next button.

The next important part is the section with the two buttons:

  1. <af:commandLink text="Previous" id="cmdPrev"
  2.       disabled="#{paginationBean.currentPage eq 1}"
  3.       actionListener="#{paginationBean.previousPage}"
  4.        partialTriggers="cmdNext" partialSubmit="true"
  5.       binding="#{paginationBean.cmdPrev}"/>
  6. <af:commandLink text="Next" id="cmdNext"  
  7.      disabled="#{paginationBean.currentPage * paginationBean.pageSize ge paginationBean.citerator.rowCount}"
  8.      partialTriggers="cmdPrev" actionListener="#{paginationBean.nextPage}" partialSubmit="true"
  9.      binding="#{paginationBean.cmdNext}"/>

The most important part about these buttons is that there is a disabled attribute that will set the initial state of the buttons. We need to have it for both buttons just in case the content presenter does not provide more elements then 1 page can handle. In that case, both buttons need to be disabled and this is exactly what the disabled attribute will do.

That's it. Create a portlet resource from the fragment.

Run the application and don't forget to set the Show flag for the content presenter template in the resource manager:

Add the content presenter to whatever page you like and add content:

First page:

After clicking on Next:

Here's the download link to the application.

That's it. Hope you enjoyed this.

Category: 
Attachment: 

Comments

where is this being read from: paginationBean.pageSize. Is it/can it be a dropdown with values (25,50,100), etc?

In my example the pageSize is just an attribute in the bean:
private int pageSize = 5;

You can of course create a dropdown list so make it dynamic.

I am using 11g and want to sort the data(list) which is paginated by using the sorting functionality should be like that of
can u help in this.

Depends on the type of data source you are using for your content presenter. If you are using a query, you can use the sorting in the query itself to sort the data.

I am using a CSV(comma separated values).
if u have any sample codes or any reference docs related to sorting of data(list) which is paginated by using an , it would help me.

Hi I have done same example if result is more then it will display scroll button otherwise scroll button will be hidden . I have done this using jquery without managed bean.

That's also a good solution. In most of these cases there are multiple solutions to achieve the same thing.
Using JQuery is fine and has some good advantages. You have maybe some more flexibility on the user interface.

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer