The Kahimyang Project Logo
Primo's Code Blog
Howtos tips and tricks
The Kahimyang Project

Building a page with infinite scroll in PrimeFaces using Waypoints jQuery plugin

Infinite scroll is a page feature where in data is automatically loaded as you scroll down to the bottom of a page. Facebook uses this feature in their "news feeds".

This demonstration uses PrimeFaces with a jQuery plugin called WayPoints.  Plugin download and documentation can be found here http://imakewebthings.com/jquery- waypoints/.  We employed PrimeFaces' <p:remoteCommand /> and <p:outputPanel /> along with Waypoints, the main component of the process.   It is Waypoints that initiates the update process that call <p:remoteCommand />, and in turn into the backing code, as soon as a Waypoint element appears at the bottom of the page/viewport.

( Live demo of this blog is here http://kahimyang.info/kauswagan/howto_blogs/java, just scroll to the bottom of page.)

Normally, in a plain HTML page, you would include Waypoints either at the bottom of the page body before the closing </body> tag or in the head section of the page like below.

<script type="text/javascript" 
    src="/kauswagan/waypoints/waypoints.js"></script>
<script type="text/javascript">
    $(document).ready(function() {
        $('.loadmore').waypoint(function(event, direction) {
            if (direction == 'down') {
                $('.loadmore').waypoint('remove');
                more_records();
                $('.loadmore').waypoint({offset: '100%'});
            }
        },{offset: '100%'});                   
    });
</script>        

Notice that offset is measured from the top of the page, 100% being the bottom of the page, which means that a trigger would occur if the Waypoint element, with a class loadmore in our example, appears at the bottom.  Once Waypoint is trigged, you have to call Waypoint again to enable the next trigger, the next time the Waypoint element reappears.

more_records() is the JavaScript code that fetches more data (line 8).

In PrimeFaces version 3.4.1 however, the above construct would continuously and successively call our <p:remoteCommand /> at the first occurrence of the trigger.   To overcome this, we implemented Waypoints in our page like the following.

In the head section.

<script type="text/javascript" 
    src="/kauswagan/waypoints/waypoints.min.js"></script>

In the body.

<p:outputPanel autoUpdate="true">
    <h:dataTable  id="philblog" rowClasses="row_1a,row_1b" 
                  var="newsObject"
                  value="#{evNewsBlogsBean.philBlogs}"  >

        <h:column>
            <!-- contents remove for clarity -->
            <h:panelGrid columns="2">

            </h:panelGrid>
        </h:column>
    </h:dataTable>

    <h:panelGroup rendered="#{evNewsBlogsBean.moreData}">

        <script type="text/javascript">
            $(document).ready(function() {
                $('.loadmore').waypoint(function(event, direction) {
                    if (direction == 'down') {
                        more_records(); 
                    }
                },{offset: '100%'}); 
            });
        </script>        

        <div class="loadmore" />

        <p:remoteCommand name="more_records"
                         update="philblog"
                         actionListener="#{evNewsBlogsBean.loadMore}" />
    </h:panelGroup>

</p:outputPanel>

Note: (4/9/2013) As of version 2 of the Waypoints plugin, the callback function parameter to waypoint in line 18, requires only one parameter, the direction.

<p:outputPanel /> is a container component that updates/loads that page section bounded by it.  All components inside it are loaded each time it is updated, each time <h:dataTable /> is updated, in our case.  This refreshes and reloads our Waypoints with fresh new page offsets.

In line 26, we have our Waypoint element which a <div /> with class "loadmore".  You can also use the ID of an element instead. Our remoteCommand in line 28 calls the backing bean and updates the <dataTable />.

more_records() is a bodyless JavaScript code in line 20, which is also the name of our <p:remoteCommand />.

The backing bean of the page should look like below although most of the data were removed for clarity.   If using MySQL to fetch data, just control the number of rows queried through the limit clause.

@ManagedBean
@ViewScoped
public class EvNewsBlogsBean implements java.io.Serializable {

    List<MyData> list;
    
    public List<MyData> getPhilBlogs () {
        if (list==null) {
            list = getList ();
        }        
        return list; 
        
    }

    public void setPhilBlogs (List<MyData> s) {        
    }
    
    List<MyData> getList () {
        return getFirstData ();
    }
    
    public void loadMore() {
        list = getNextData ();        
    }

    public class MyData {
        private String member1;
        private String more;
        /*
           public getters/setters
        */
    }
    
}

In the page snippet above in line 14, we stop to render the entire Waypoints block on certain condition which is handled by #{evNewsBlogsBean.moreData}.  This is either we reached the end of data or a number of rows limit has been reached.

That's it Good Luck.

RSS Logo



Related articles

Comment icon   Comments (Newest first)

Recent posts in Java/JSF category
Blue dot icon Using Rhinoslider with image and youtube content in JSF pages
Blue dot icon A dynamic standard sitemap.xml with Google image extension implemented as a Java Servlet
Blue dot icon Creating a Facebook-like panel with slim scrollbars and infinite scrolling in PrimeFaces
Blue dot icon Generating XML RSS 2 feeds with JDOM 2 with a servlet
Blue dot icon Building a page with infinite scroll in PrimeFaces using Waypoints jQuery plugin
Blue dot icon Implementing a collapsible ui:repeat rows in JSF
Blue dot icon Validating an email address in PrimeFaces p:inputText field with p:ajax





Most popular articles
Blue dot icon Using Expect script to automate SSH logins and do routine tasks accross multiple hosts   (15341)
Blue dot icon How to setup Tomcat 7 as your primary webserver on Debian Squeeze    (14070)
Blue dot icon How to setup FLV streaming with crtmpserver C++ RTMP server   (9830)
Blue dot icon A Java class for sending multipart Email messages through your Gmail account    (6972)
Blue dot icon How to use Google Translate's Text to Speech (TTS) services in your web page using Servlet   (5666)
Blue dot icon Speed up Primefaces page load with p:remoteCommand partial update   (5467)
Blue dot icon Building a mobile website with JSF 2 core and JQuery Mobile 1.0   (5317)
Blue dot icon Google Map-Adding markers, info window, circle, small control, and events in Javascript    (5218)