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:
- Add a row: An item is created and added to the table. This item is inserted into the table and is selected. The table is sorted and the table scroll bar positions to show the selected item.
- Update a row: An item name is changed and the row is updated. The updated item row is selected. The table is sorted and the table scroll bar positions to show the selected item.
- Delete a row: An item is selected and deleted. The following item is selected and the scroll bar is set for the selected item.
The following is a screenshot of the completed example app:

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.
- The JSF page (index.xhtml) has the UI elements - the data table, buttons for add, update and delete functions and a status output text. This also defines a jQuery function that determines the
scrolTop
and scrolls to the selected item. - An Item class (Item.java) represents an item, shown as a row in the data table.
- A managed bean class (ItemsTableBean.java) has functions to create item data, populate the table and has listener methods that act on the table data for add, update and delete functions.
4. The Custom Scroll Function
The following are described in this section:
- The input required to determine
scrollTop
- The code for JSF page and the managed bean class
- The jQuery function
4.1. The Input
The following info (four attributes) is needed to determine a scroll position:
- Number of rows (items) in the table (or the size of the collection populating the table).
- The index of the row (item) to be selected.
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}" />
- The height of the table element; the
height()
method returns this in jQuery. - The height of the scroll view (including all the non-visible rows) of the table element; the
scrollHeight
property gets the value of this in jQuery.
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
- Download source code here: JSFDataTableScrollExample.zip
6. Useful Links
- jQuery: https://jquery.com/
- PrimeFaces: http://primefaces.org/