primefaces datatableThe dataTable is a key component of JSF architecture. It can display Objects in a Collection or an Array where each Object represents one row in the table and columns match instance variables in the Object. In this tutorial we will show how to create advanced datatable examples using PrimeFaces library.

Dynamic dataTable example

A common need for many applications is to create tabular data with a dynamic number of columns. Columns can be added programmaticaly, thus you can use the same dataTable for displaying different kind of models.

Creating a dynamic datatable with PrimeFaces is really easy: instead of using the standard <p:column> tag, use the <p:columns> which references the list of columns (via the value attribute) that are mantained in a Collection.

Here is a simple example:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">

<h:head>

</h:head>

<h:body>
    <h:form id="form" prependId="false">

        <h3>Dynamic Data table example</h3>
        <p:dataTable var="data" value="#{tableBean.people}">
            <p:columns value="#{tableBean.columns}" var="column"
                columnIndexVar="colIndex">
                <f:facet name="header">
                #{column.header}
                </f:facet>

            #{data[column.property]}
            </p:columns>
        </p:dataTable>

    </h:form>
</h:body>
</html>

This is the JSF Managed Bean used:

package com.sample.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import model.People;


@ManagedBean
public class TableBean implements Serializable {

    private List<ColumnModel> columns;
    private List<People> people;

    private String columnName;

    public TableBean() {
        createDynamicColumns();
        addPeople();
    }

    private void addPeople() {
        people = new ArrayList<People>();

        People w1 = new People("Homer Simpson","The father",48);
        People w2 = new People("Marge Simpson","The mother",46);
        People w3 = new People("Bart Simpson","Oldest child",11);
        People w4 = new People("Lisa Simpson","Sister of Bart",8);

        people.add(w1);
        people.add(w2);
        people.add(w3);
        people.add(w4);
    }

    private void createDynamicColumns() {

        columns = new ArrayList<ColumnModel>();
        columns.add(new ColumnModel("Name", "name"));
        columns.add(new ColumnModel("Role", "role"));
        columns.add(new ColumnModel("Age", "age"));
    }

    public List<People> getPeople() {
        return people;
    }

    public void setPeople(List<People> people) {
        this.people = people;
    }

    public List<ColumnModel> getColumns() {
        return columns;
    }

    public String getColumnName() {
        return columnName;
    }

    public void setColumnName(String columnName) {
        this.columnName = columnName;
    }

    static public class ColumnModel implements Serializable {

        private String header;
        private String property;

        public ColumnModel(String header, String property) {
            this.header = header;
            this.property = property;
        }

        public String getHeader() {
            return header;
        }

        public String getProperty() {
            return property;
        }
    }
}

And here's the expected result:

primefaces datatable tutorial


Primefaces editable dataTable

When your tabular data is not read-only, you need to enable editing of your dataTable cells. This can be achieved in many ways: for example you might add a button which fires a popup with the editable fields.

Creating an editable datatable with PrimeFaces just requires wrapping each column into <p:cellEditor>. The <p:cellEditor> contains both an output text and an input text which will be fired when you are in edit mode. In order to switch to the editing mode, add a column containing <p:rowEditor />. That's all. No changes required in the Bean Model.

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">

<h:head>

</h:head>
<h2>Editable Datatable</h2>
<h:body>
    <h:form id="jsfexample">
        <p:panelGrid columns="2">
            <f:facet name="header">  
                Basic PanelGrid  
           </f:facet>
            <h:outputLabel for="key" value="Enter key" />
            <p:inputText id="key" value="#{manager.key}" />

            <h:outputLabel for="value" value="Enter value" />
            <p:inputText id="value" value="#{manager.value}" />

            <p:commandButton action="#{manager.save}" update="mydata"
                value="Save" icon="ui-icon-check" style="margin:0" />

        </p:panelGrid>

        <p:dataTable value="#{manager.cacheList}" var="item" id="mydata">

            <p:column headerText="Key">
                <p:cellEditor>
                    <f:facet name="output">
                        <h:outputText value="#{item.key}" />
                    </f:facet>
                    <f:facet name="input">
                        <h:inputText value="#{item.key}" />
                    </f:facet>
                </p:cellEditor>
            </p:column>

 

            <p:column headerText="Value">
                <p:cellEditor>
                    <f:facet name="output">
                        <h:outputText value="#{item.value}" />
                    </f:facet>
                    <f:facet name="input">
                        <h:inputText value="#{item.value}" />
                    </f:facet>
                </p:cellEditor>
            </p:column>


            <p:column headerText="Options" style="width:50px">
                <p:rowEditor />
            </p:column>
        </p:dataTable>
    </h:form>
</h:body>
</html>

This is the JSF Bean which is used in this example. For the full code example (which includes a SingletonEJB and the Property POJO download the code at the end of the article).

package com.sample.bean;


import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;
import javax.servlet.http.HttpServletRequest;

import com.sample.ejb.SingletonBean;
import com.sample.model.Property;

@ManagedBean(name="manager")
public class PropertyManager {
  
    @EJB
    SingletonBean ejb;
    
    ArrayList  cacheList;
    private String key;
    private String value; 

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public void save() {
        ejb.put(key, value);
        
    }

    public void clear() {
         
        cacheList.clear();
    
    }
    public List getCacheList() {
        return ejb.getCache();
    }

}

And here's the expected output:

primefaces datatable tutorial


Primefaces dataTable with details popup

If all of your tabular data does not fit in the rows, then you should provide a Master-Detail view of your data. The simplest way to achieve this is by means of a detail popup.

Creating a details popup requires just two tags: a <p:rowExpansion> containing the panel to be displayed and a <p:rowToggler /> which fires the popup. That's all!

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">

<h:head>

</h:head>
<h2>Expandable Datatable</h2>
<h:body>
    <h:form id="jsfexample">
        <p:panelGrid columns="2">
            <f:facet name="header">  
                Basic PanelGrid  
           </f:facet>
            <h:outputLabel for="key" value="Enter key" />
            <p:inputText id="key" value="#{manager.key}" />

            <h:outputLabel for="value" value="Enter value" />
            <p:inputText id="value" value="#{manager.value}" />

            <p:commandButton action="#{manager.save}" update="mydata"
                value="Save" icon="ui-icon-check" style="margin:0" />


            <h:messages />


        </p:panelGrid>

        <p:dataTable value="#{manager.cacheList}" var="item" id="mydata">
            <p:column style="width:16px">
                <p:rowToggler />
            </p:column>
            <p:column style="width:150px">

                <f:facet name="header">Key</f:facet>
                <h:outputText value="#{item.key}" />

            </p:column>
            <p:column style="width:150px">

                <f:facet name="header">Value</f:facet>
                <h:outputText value="#{item.value}" />

            </p:column>
            <p:rowExpansion>
                <h:panelGrid id="display" columns="2" cellpadding="4"
                    style="width:300px;" styleClass="ui-widget-content"
                    columnClasses="label, value">

                    <h:outputText value="Extra data:" />
                    <h:outputText id="extra" value="#{item.random}" />

                    <h:outputText value="Date:" />
                    <h:outputText id="date" value="#{item.date}" />
                </h:panelGrid>

            </p:rowExpansion>
        </p:dataTable>
    </h:form>
</h:body>
</html>

Here's a snaphost of it:

primefaces datatable tutorial


Primefaces Filtered dataTable

Filtering data leverages Primefaces powerful AJAX functionalities by adding text or combo filtering fields.

In order to use filtering on a column, add the parameters filterMatchMode and filterBy to it. If you need to add a Combobox filter, add the additional parameter filterOptions which references a Collection/Array of  SelectItem

Here's an example of it:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">

<h:head>

</h:head>
<h2>Filtered Datatable</h2>
<h:body>
    <h:form id="jsfexample">
        <p:panelGrid columns="2">
            <f:facet name="header">  
                Basic PanelGrid  
           </f:facet>
            <h:outputLabel for="key" value="Enter key" />
            <p:inputText id="key" value="#{manager.key}" />

            <h:outputLabel for="value" value="Enter value" />
            <p:inputText id="value" value="#{manager.value}" />

            <p:commandButton action="#{manager.save}" update="mydata"
                value="Save" icon="ui-icon-check" style="margin:0" />
            <p:commandButton action="#{manager.clear}" update="mydata"
                value="Delete" icon="ui-icon-cancel" style="margin:0" />

            <h:messages />


        </p:panelGrid>

        <p:dataTable value="#{manager.cacheList}" var="item" id="mydata">
            <p:column style="width:150px" filterMatchMode="contains"
                filterBy="#{item.key}">

                <f:facet name="header">Key</f:facet>
                <h:outputText value="#{item.key}" />

            </p:column>
            <p:column style="width:150px" filterMatchMode="exact"
                filterOptions="#{manager.valueList}" filterBy="#{item.value}">

                <f:facet name="header">Value</f:facet>
                <h:outputText value="#{item.value}" />

            </p:column>

        </p:dataTable>
    </h:form>
</h:body>
</html>

And here's the JSF Bean with just the necessary changes:

public class PropertyManager {
 
    @EJB
    SingletonBean ejb;
    
    ArrayList  cacheList;
    
    // Used for filtering data by filter.xhtml
    static List<SelectItem> valueList = new ArrayList<SelectItem>();
    
    
 // .... All other methods stay the same

    public void save() {
        ejb.put(key, value);
        
        // Adding entry to the Filter Combo box
        valueList.add(new SelectItem(value));
            
    }


}

Here's a snapshot of it:

primefaces datatable


dataTable frozen Rows

DataTable rows can be fixed in a scrollable table by using the frozenRows attribute that defines the number of rows to freeze from the start. Much the same way you can use the frozenColumns attribute to define the number of rows to freeze.

Let's see a practical example of it:

<!DOCTYPE html>
<html xmlns="http://www.w3c.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
 
    
<h:form> 
     <p:dataTable var="c" value="#{dataScrollerView.countries}" scrollable="true" scrollHeight="150" scrollWidth="300" frozenColumns="1">
 
        <p:column headerText="Code" footerText="Code">
            <h:outputText value="#{c.code}" />
        </p:column>
        <p:column headerText="Name" footerText="Name">
            <h:outputText value="#{c.name}" />
        </p:column>
        <p:column headerText="Language" footerText="Language">
            <h:outputText value="#{c.language}" />
        </p:column>
         
    </p:dataTable>
</h:form>
</h:body>
</html>

As you can see from the following picture, the first column (frozenColumns = 1) is frozen so it will stay fixed as you scroll your dataTable to the right:

primefaces frozen columns

dataTable live scroll

Simple scrolling renders all data to client in one shot. When dealing with a huge set of data, live scrolling can be a lifesaver. In this case data is fetched whenever the scrollbar reaches bottom. Set liveScroll attribute of the dataTable to enable this option. Here is an example of it:

<!DOCTYPE html>
<html xmlns="http://www.w3c.org/1999/xhtml"
	xmlns:h="http://xmlns.jcp.org/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>


	<h:form>
		<p:dataTable var="c" value="#{dataScrollerView.countries}"
			scrollRows="20" scrollable="true" liveScroll="true"
			scrollHeight="150" style="margin-bottom:0">

			<p:column headerText="Code" footerText="Code">
				<h:outputText value="#{c.code}" />
			</p:column>
			<p:column headerText="Name" footerText="Name">
				<h:outputText value="#{c.name}" />
			</p:column>

		</p:dataTable>
	</h:form>
</h:body>
</html>

Here is how the dataTable will be rendered:

datatable liveupload

Scrolling has 3 modes; x, y and x-y scrolling that are defined by scrollHeight and scrollWidth. These two scroll attributes can be defined using integer values indicating fixed pixels or percentages relative to the container dimensions.

Download code for this article

0
0
0
s2sdefault