Java Quiz Player

PrimeFaces p:dataTable - Scroll to Selected Row

Apr 15, 2015

This article shows customized scrolling to a row that is newly selected after it is added, updated or deleted in a PrimeFaces data table. The required scrolling is achieved using a jQuery function.

The article's example uses JSF 2.0 with PrimeFaces 5.1 and Apache MyFaces 2.0 deployed on a Tomcat 6 web server.

1. Overview

PrimeFaces is an open source user interface component library for JavaServer Faces (JSF) based applications. JSF is a server-side component framework for building Java technology based web applications.

The example has a data table with each row representing an Item. The table has just one column (for brevity), item name. The items in the table are sorted by item name in an ascending order. This sort order is maintained after a new item is added or when an item name is changed.

The user interface has a table (p:dataTable) and buttons (p:commandButton) for add, update and delete functions. Note that the data table and the buttons make ajax requests.

The following are the details of the functions:

The following is a screenshot of the completed example app:

image

2. On Scrolling

By default the data table scrolling mechanism does not scroll to a selected row, for example after adding a new row. Note this is specific to PrimeFaces (other JSF UI libraries may have different behaviour). By using jQuery the scrolling is customized to achieve the requirement specified above. Note that Primefaces uses jQuery as its default JavaScript library.

To scroll to a particular position vertically for the data table element, its scrollTop property needs to be determined and set. It is the number of pixels that the content of an element is scrolled upward. jQuery's scrollTop() method is used to get the current scroll bar position value or set a new value; the value is an integer and is measured in pixels.

In this example the scrollTop value for the selected item is determined.

3. The Example

The example app has a JSF page and two Java classes.

4. The Custom Scroll Function

The following are described in this section:

4.1. The Input

The following info (four attributes) is needed to determine a scroll position:

The above two values are determined from the managed bean's get methods and are populated to hidden fields on the JSF page. The hidden element values are accessed in the jQuery function.

<h:inputHidden id="hiddenSizeId" value="#{bean.itemsSize}" />
<h:inputHidden id="hiddenIxId" value="#{bean.newItemIx}" />
var height = $("#scrollContent").height();
var scrollHt = $("#scrollContent").prop("scrollHeight");

The scrollContent in the above code is a data table (or div element which has "overflow:auto" property set (sets the scroll bars)) and its content flows beyond the initially defined height.

4.2. The Code

The following are the code snippets of the JSF page and the managed bean. The JSF page's code shows the snippets of the data table and the add button. The managed bean's code shows the add button's ajax listener's method.

The data table:

<p:dataTable id="table"
    var="item" value="#{bean.items}" 
    selectionMode="single" 
    selection="#{bean.selectedItem}" 
    rowKey="#{item.name}"
    scrollable="true" scrollHeight="200" height="250">
			
    <p:ajax event="rowSelect"
        listener="#{bean.onRowSelect}"
        update=":fm:msg"/>

    <p:column headerText="ITEMS">
        <h:outputText value="#{item.name}"/>
    </p:column>
</p:dataTable>

The add item function is executed by clicking the Add button. The following is the button's code:

<p:commandButton value="Add">
    <p:ajax update=":fm:table :fm:msg :fm:hiddenSizeId :fm:hiddenIxId"
        listener="#{bean.addListener}"
        oncomplete="getNewItemPos()"/>
</p:commandButton>

The bean's listener method is executed and the newly inserted row index (after sorting) and the total items are determined. The bean's addListener() method is as follows:

public void addListener() {

    Item item = createItem();
    items.add(item);
    Collections.sort(items);
    setSelectedItem(item);

    itemsSize = items.size();
    newItemIx = items.indexOf(item);
}

The itemsSize and newItemIx bean properties are updated to JSF page's h:inputHidden hidden elements hiddenSizeId and hiddenIxId respectively.

<h:inputHidden id="hiddenSizeId" value="#{bean.itemsSize}" />
<h:inputHidden id="hiddenIxId" value="#{bean.newItemIx}" />

Finally, the jQuery function getNewItemPos() is executed. This function is called from the Add, Update and Delete command button's "oncomplete" call (this executes the client side script after the ajax request is complete). This function sets the data table scroll bar to the newly added and selected item.

4.3. The jQuery Function

This is the code for the getNewItemPos() function.

The following four values are already explained above.

var noOfItems = $("#fm\\:hiddenSizeId").val();
var itemIx = $("#fm\\:hiddenIxId").val();
var bucketHt = $("#fm\\:dt .ui-datatable-scrollable-body").height();
var scrollHt =
    $("#fm\\:dt .ui-datatable-scrollable-body").prop("scrollHeight");

The following are determined (and the variable names are self-explanatory):

var itemHt = parseInt(iScrollHeight) / parseInt(noOfItems);
var noItemsInBucket = parseInt(bucketHt) / parseFloat(itemHt);
var itemNo = parseInt(itemIx) + 1;
var targetBucket = parseInt(itemNo) / parseFloat(noItemsInBucket);
var halfBucketHt = parseInt(bucketHt) / 2;

Get the scroll position:

var scrollPos = (parseInt(bucketHt) * (parseFloat(targetBucket) - 1)) + 
    parseFloat(halfBucketHt);
var scrollPosInt = Math.round(parseFloat(scrollPos));

Finally, scroll to the selected item by setting the scrollTop value:

$('#fm\\:dt .ui-datatable-scrollable-body').animate({
    scrollTop:scrollPosInt});

NOTE: In the above code the variables with "Ht" suffix and "scrollPos" are measured in pixels.

5. Download and Try

6. Useful Links

Return to top