PrimeFaces 5 Features

This tutorial highlights the new features added as part of the PrimeFaces 5 release. PrimeFaces 5 has been announced and shipped with set of new components. We’ve published set of tutorials that covered the PrimeFaces 4 earlier in our blog. To summarize, PrimeFaces 5 comes up with set of new components and lot of minor enhancements in the framework.  At the end of this tutorial, I have uploaded the source code for this tutorial. You can download that and try the PrimeFaces 5 features in your environment. PrimeFaces 5 is compatible to JSF 2.0, JSF 2.1 and JSF 2.2If you have any questions, please write it in the comments section.

The following are the new components added as part of the new release.

  1. DataScroller
  2. Cache
  3. Spotlight
  4. ColumnToggler
  5. ContentFlow

If you are not familiar with the PrimeFaces framework or JSF, please read the list of articles suggested below to get basic idea of the frameworks.

The prerequisite or knowledge for this tutorial,

  • Java Server Faces (JSF) concepts
  • PrimeFaces
  • EclipseLink / JPA (This requires to display the data from the database)

Lets look at the examples.

1. DataScroller

DataScroller displays a collection of data with on demand loading using scrolling.

1.1 DataScroller Basic Info

DataScroller - Basic Info

1.2 DataScroller Attributes

DataScroller - Attributes

  1. DataScroller requires a collection of data to display, when the page is scrolled down, datascroller will do a request with ajax to fetch the new chunk of data and append them at the bottom.
  2. Defaulted scroll mode is the document, thus, the scrolling against page is monitored by the DataScroller component and at every time you get reached into the bottom of the page, an ajax request has been initiated cause data fetching with the same amount that you’ve specified in the chunkSize.
  3. The other applicable value for the mode attribute is inline which cause scrolling event be applied against the DataScroller itself.

1.3 DataScroller Demo

Here is the implementation for the DataScroller component. Lets look at the details of the implementation. Here I have listed the primefaces view and JSF managed bean.

index.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:p="http://primefaces.org/ui">
	<h:head>
		<script name="jquery/jquery.js" library="primefaces"></script>
	</h:head>
	<f:view>
		<h:form prependId="false">
			<h2>JavaBeat Tutorials</h2>
			<h2>Primefaces 5 New Components !</h2>
			<div style="width: 700px;border: 1px;border-style: dotted;">
			<h:panelGrid columns="2">
				<h:outputText value="Enter Employee Name:"/>
				<p:inputText value="#{registrationManagedBean.employee.employeeName}"></p:inputText>
				<h:outputText value="Enter Employee Address Country:"/>
				<p:inputText value="#{registrationManagedBean.employee.address.addressCountry}"></p:inputText>
				<h:outputText value="Enter Employee Address City:"/>
				<p:inputText value="#{registrationManagedBean.employee.address.addressCity}"></p:inputText>
			</h:panelGrid>
			<p:commandButton value="Register" action="#{registrationManagedBean.register}" ajax="false"/>
			<p:separator/>
			<p:dataScroller value="#{registrationManagedBean.employees}" var="employee" chunkSize="10" mode="inline" scrollHeight="80">
			        <f:facet name="header">
			            Employees
			        </f:facet>
			        <f:facet name="loader">
			            <p:commandButton value="Scroll Down to Load More Employees" type="button"></p:commandButton>
			        </f:facet>
			        <h:panelGrid columns="2" style="width:100%" columnClasses="logo,detail">
			            <p:outputPanel>
			                <h:panelGrid columns="2" cellpadding="5">
			                    <h:outputText value="#{employee.employeeName}" style="font-weight: bold"/>
			                </h:panelGrid>
			            </p:outputPanel>
			        </h:panelGrid>
			</p:dataScroller>
			</div>
		</h:form>
	</f:view>
</html>

RegistrationManagedBean.java

package net.javabeat.primefaces.managedbeans;

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

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import net.javabeat.jpa.data.Employee;

import com.google.common.collect.Lists;

@ManagedBean
@SessionScoped
public class RegistrationManagedBean {

	private Employee employee = new Employee();

	private List<Employee> employees = new ArrayList<Employee>();
	private EntityManagerFactory factory = null;
	private EntityManager service = null;

	{
		factory = Persistence.createEntityManagerFactory("persistenceUnit");
		service = factory.createEntityManager();
	}

	public RegistrationManagedBean() {

	}

	@SuppressWarnings({ "unchecked"})
	@PostConstruct
	public void fetchEmployees() {
		for (int i = 1; i < 100; i++) {
			Employee emp = new Employee();
			emp.setEmployeeName("Employee" + i);
			emp.getAddress().setAddressCountry("Address" + i);
			emp.getAddress().setAddressCity("Address" + i);
			this.service.getTransaction().begin();
			this.service.persist(emp);
			this.service.getTransaction().commit();
			emp = new Employee();
		}
		this.employees = Lists.newArrayList(this.service.createQuery("select e from Employee e").getResultList());
	}

	public Employee getEmployee() {
		return employee;
	}

	public void setEmployee(Employee employee) {
		this.employee = employee;
	}

	public List<Employee> getEmployees() {
		return employees;
	}

	public void setEmployees(List<Employee> employees) {
		this.employees = employees;
	}

	@SuppressWarnings("unchecked")
	public String register() {
		this.service.getTransaction().begin();
		this.service.persist(employee);
		this.service.getTransaction().commit();
		this.employees = Lists.newArrayList(this.service.createQuery("select e from Employee e").getResultList());
		this.employee = new Employee();
		return "";
	}
}
  • Scrolling mode is inline, so the scrolling listener would be against the DataScroller itself.
  • ScrollHeight attribute is set to be 80, so that two employees should be shown. You will be able of scrolling down until you’ve finished the first chunk of data which is 10 employees as we’ve specified in the chunkSize.
  • Once we’ve reached into the last employee in the already first fetched chunk, an Ajax request has been initiated for fetching the next chunk of data and so on.
  • For simplifying the concept, we’ve used the loader facet which would be shown at every time you’ve finished scrolling of data chunk.
  • Once you’ve pressed on the button an Ajax loader image will be shown.
  • By eliminating the loader button, the chunk of data should be fetched when reaching into bottom while scrolling.

DataScroller - First Chunk

DataScroller - Fetch Second Chunk

DataScroller - Second Chunk Fetched

2. Cache

Cache component is used to reduce page load time by caching the content after initial rendering. It is one of the useful component added as part of the PrimeFaces 5 release.

2.1 Cache Basic Info

Cache Basic Info

2.2 Cache Attributes

Cache Attributes

2.3 Cache Demo

A cache store is required to use the cache component, two different providers are supported as cache implementations are EHCache and Hazelcast. Selected provider should be configured in the web.xml via a context-param.

Also there are few more steps required for configuring an EHCache. Defining cache regions are supported by using the cache tag which contains set of attributes used for defining the all required aspects of caching mechanism.

The Wiring of cache component with the cache mechanism that defined in the ehcache.xml is done via mentioning the cache name inside the XML in the region attribute for the cache component.

Once the page is loaded initially, content inside p:cache component is cached inside the cache region of the cache provider. Postbacks on the same page or reopening the page will retrieve the output from cache instead of rendering the content regularly.

The demonstration below shows you the impact of using the cache component into resolving the #{registrationManagedBean.employees} where the invocation of getEmployees() should be processed while the invocation isn’t Postback. After that every invocation is loaded from the cache.

index.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:p="http://primefaces.org/ui">
	<h:head>
		<script name="jquery/jquery.js" library="primefaces"></script>
	</h:head>
	<f:view>
		<h:form prependId="false">
			<h2>JavaBeat Tutorials</h2>
			<h2>Primefaces + Cache</h2>
			<div style="width: 700px;border: 1px;border-style: dotted;">
			<h:panelGrid columns="2">
				<h:outputText value="Enter Employee Name:"/>
				<p:inputText value="#{registrationManagedBean.employee.employeeName}"></p:inputText>
				<h:outputText value="Enter Employee Address Country:"/>
				<p:inputText value="#{registrationManagedBean.employee.address.addressCountry}"></p:inputText>
				<h:outputText value="Enter Employee Address City:"/>
				<p:inputText value="#{registrationManagedBean.employee.address.addressCity}"></p:inputText>
			</h:panelGrid>
			<p:commandButton value="Register" action="#{registrationManagedBean.register}" ajax="false"/>
			<p:separator/>
			<p:cache region="cache" key="dataScrollerKey">
			<p:dataScroller value="#{registrationManagedBean.employees}" var="employee" chunkSize="10" mode="inline" scrollHeight="80">
			        <f:facet name="header">
			            Employees
			        </f:facet>
			        <f:facet name="loader">
			            <p:commandButton value="Scroll Down to Load More Employees" type="button"></p:commandButton>
			        </f:facet>
			        <h:panelGrid columns="2" style="width:100%" columnClasses="logo,detail">
			            <p:outputPanel>
			                <h:panelGrid columns="2" cellpadding="5">
			                    <h:outputText value="#{employee.employeeName}" style="font-weight: bold"/>
			                </h:panelGrid>
			            </p:outputPanel>
			        </h:panelGrid>
			</p:dataScroller>
			</p:cache>
			</div>
		</h:form>
	</f:view>
</html>

RegistrationManagedBean.java

package net.javabeat.primefaces.managedbeans;

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

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import net.javabeat.jpa.data.Employee;

import com.google.common.collect.Lists;

@ManagedBean
@SessionScoped
public class RegistrationManagedBean {

	private Employee employee = new Employee();

	private List<Employee> employees = new ArrayList<Employee>();
	private EntityManagerFactory factory = null;
	private EntityManager service = null;

	{
		factory = Persistence.createEntityManagerFactory("persistenceUnit");
		service = factory.createEntityManager();
	}

	public RegistrationManagedBean() {

	}

	@SuppressWarnings({ "unchecked"})
	@PostConstruct
	public void fetchEmployees() {
		for (int i = 1; i < 100; i++) {
			Employee emp = new Employee();
			emp.setEmployeeName("Employee" + i);
			emp.getAddress().setAddressCountry("Address" + i);
			emp.getAddress().setAddressCity("Address" + i);
			this.service.getTransaction().begin();
			this.service.persist(emp);
			this.service.getTransaction().commit();
			emp = new Employee();
		}
		this.employees = Lists.newArrayList(this.service.createQuery("select e from Employee e").getResultList());
	}

	public Employee getEmployee() {
		return employee;
	}

	public void setEmployee(Employee employee) {
		this.employee = employee;
	}

	public List<Employee> getEmployees() {
		if(FacesContext.getCurrentInstance().isPostback()){
			System.out.println(":: Postpack invocation :: Employees List is loaded from the cache ::");
		}
		else {
			System.out.println(":: Initial Invocation :: Employees List is loaded and returned ::");
		}
		return employees;
	}

	public void setEmployees(List<Employee> employees) {
		this.employees = employees;
	}

	@SuppressWarnings("unchecked")
	public String register() {
		this.service.getTransaction().begin();
		this.service.persist(employee);
		this.service.getTransaction().commit();
		this.employees = Lists.newArrayList(this.service.createQuery("select e from Employee e").getResultList());
		this.employee = new Employee();
		return "";
	}
}

ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
	monitoring="autodetect" dynamicConfig="true">
	<diskStore path="java.io.tmpdir" />
	<defaultCache maxEntriesLocalHeap="10000" eternal="false"
		timeToIdleSeconds="120" timeToLiveSeconds="120" diskSpoolBufferSizeMB="30"
		maxEntriesLocalDisk="10000000" diskExpiryThreadIntervalSeconds="120"
		memoryStoreEvictionPolicy="LRU">
		<persistence strategy="localTempSwap"/>
	</defaultCache>
	<cache name="cache" maxEntriesLocalHeap="10000" eternal="false"
		timeToIdleSeconds="120" timeToLiveSeconds="120" diskSpoolBufferSizeMB="30"
		maxEntriesLocalDisk="10000000" diskExpiryThreadIntervalSeconds="120"
		memoryStoreEvictionPolicy="LRU">
		<persistence strategy="localTempSwap" />
	</cache>
</ehcache>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" metadata-complete="true" version="2.5">
	<context-param>
		<description>State saving method: 'client' or 'server'
						(=default). See JSF Specification 2.5.2
		</description>
		<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
		<param-value>server</param-value>
	</context-param>
	<context-param>
		<param-name>javax.faces.application.CONFIG_FILES</param-name>
		<param-value>/WEB-INF/faces-config.xml</param-value>
	</context-param>
	<context-param>
		<param-name>primefaces.CACHE_PROVIDER</param-name>
		<param-value>org.primefaces.cache.EHCacheProvider</param-value>
	</context-param>
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>/faces/*</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.xhtml</url-pattern>
	</servlet-mapping>
	<listener>
		<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
	</listener>
</web-app>

pom.xml (Maven Build)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>next.javabeat.jsf</groupId>
	<artifactId>JavaBeat-Primefaces-JPA</artifactId>
	<packaging>war</packaging>
	<version>1.0</version>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.7</java.version>
		<junit.version>4.9</junit.version>
		<slf4j.version>1.6.4</slf4j.version>
		<logback.version>1.0.1</logback.version>
		<log4j.version>1.2.14</log4j.version>

		<servlet.version>2.5</servlet.version>
		<jsp.version>2.1</jsp.version>
		<jstl.version>1.2</jstl.version>
		<taglibs-standard.version>1.1.2</taglibs-standard.version>

		<maven.compiler.plugin>2.3.2</maven.compiler.plugin>
		<maven.failsafe.plugin>2.4.3-alpha-1</maven.failsafe.plugin>

	</properties>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<id>prime-repo</id>
			<name>PrimeFaces Maven Repository</name>
			<url>http://repository.primefaces.org</url>
			<layout>default</layout>
		</repository>
	</repositories>

	<dependencies>
		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>${servlet.version}</version>
			<scope>provided</scope>
		</dependency>
		<!-- Faces Implementation -->
		<dependency>
			<groupId>com.sun.faces</groupId>
			<artifactId>jsf-impl</artifactId>
			<version>2.2.4</version>
		</dependency>
		<!-- Faces Library -->
		<dependency>
			<groupId>com.sun.faces</groupId>
			<artifactId>jsf-api</artifactId>
			<version>2.2.4</version>
		</dependency>
		<!-- Primefaces Version 5 -->
		<dependency>
			<groupId>org.primefaces</groupId>
			<artifactId>primefaces</artifactId>
			<version>5.0.RC2</version>
		</dependency>
		<!-- JSP Library -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.1</version>
		</dependency>
		<!-- JSTL Library -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.1.2</version>
		</dependency>
		<!-- Google List Library -->
		<dependency>
			<groupId>com.google.guava</groupId>
			<artifactId>guava</artifactId>
			<version>r09</version>
		</dependency>
		<!-- Dependencies for Eclipse JPA Persistence API -->
		<dependency>
			<groupId>org.eclipse.persistence</groupId>
			<artifactId>eclipselink</artifactId>
			<version>2.5.0-RC1</version>
			<exclusions>
				<exclusion>
					<groupId>org.eclipse.persistence</groupId>
					<artifactId>commonj.sdo</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<!-- Dependency for MySql Java connector -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.30</version>
		</dependency>
                <!-- Dependency for ehcache provider -->
		<dependency>
			<groupId>net.sf.ehcache</groupId>
			<artifactId>ehcache-core</artifactId>
			<version>2.6.9</version>
		</dependency>
	</dependencies>

</project>

Cache - Demo

  • Even we’ve provided a message print when the request become Postback, but it’s not shown.
  • The second Postback request is processed by the cache, thus the message of Postback in the getEmployees() hasn’t invoked.
  • Initial invocation has been displayed three times, cause nature of JSF lifecycle.

3. Spotlight

Spotlight highlights a certain component on page.

3.1 Spotlight Basic Info

Spotlight Basic Info

3.2 Spotlight Attributes

Spotlight Attributes

3.3 Spotlight Demo

Spotlight component is accessed by using the client side API. Before registration of new employee, nothing shown at all. Once Register action has been activated by clicking , an employees Table got highlighted for a while and all components are disabled except that highlighted one. Once the action has been returned and Register method finished, the highlight is never seen and everything got be normal again.
index.hxtml

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:p="http://primefaces.org/ui">
	<h:head>
		<script name="jquery/jquery.js" library="primefaces"></script>
	</h:head>
	<f:view>
		<h:form prependId="false">
			<h2>JavaBeat Tutorials</h2>
			<h2>Primefaces + Cache</h2>
			<div style="width: 700px;border: 1px;border-style: dotted;">
			<h:panelGrid columns="2">
				<h:outputText value="Enter Employee Name:"/>
				<p:inputText value="#{registrationManagedBean.employee.employeeName}"></p:inputText>
				<h:outputText value="Enter Employee Address Country:"/>
				<p:inputText value="#{registrationManagedBean.employee.address.addressCountry}"></p:inputText>
				<h:outputText value="Enter Employee Address City:"/>
				<p:inputText value="#{registrationManagedBean.employee.address.addressCity}"></p:inputText>
			</h:panelGrid>
			<p:commandButton value="Register" action="#{registrationManagedBean.register}" ajax="false" onclick="PF('spot').show()"/>
			<p:spotlight target="dataScroller" widgetVar="spot"></p:spotlight>
			<p:separator/>
			<p:dataScroller id="dataScroller" value="#{registrationManagedBean.employees}" var="employee" chunkSize="10" mode="inline" scrollHeight="80">
			        <f:facet name="header">
			            Employees
			        </f:facet>
			        <f:facet name="loader">
			            <p:commandButton value="Scroll Down to Load More Employees" type="button"></p:commandButton>
			        </f:facet>
			        <h:panelGrid columns="2" style="width:100%" columnClasses="logo,detail">
			            <p:outputPanel>
			                <h:panelGrid columns="2" cellpadding="5">
			                    <h:outputText value="#{employee.employeeName}" style="font-weight: bold"/>
			                </h:panelGrid>
			            </p:outputPanel>
			        </h:panelGrid>
			</p:dataScroller>
			</div>
		</h:form>
	</f:view>
</html>

RegistrationManagedBean.java

package net.javabeat.primefaces.managedbeans;

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

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import net.javabeat.jpa.data.Employee;

import com.google.common.collect.Lists;

@ManagedBean
@SessionScoped
public class RegistrationManagedBean {

	private Employee employee = new Employee();

	private List<Employee> employees = new ArrayList<Employee>();
	private EntityManagerFactory factory = null;
	private EntityManager service = null;

	{
		factory = Persistence.createEntityManagerFactory("persistenceUnit");
		service = factory.createEntityManager();
	}

	public RegistrationManagedBean() {

	}

	@SuppressWarnings({ "unchecked"})
	@PostConstruct
	public void fetchEmployees() {
		this.employees = Lists.newArrayList(this.service.createQuery("select e from Employee e").getResultList());
	}

	public Employee getEmployee() {
		return employee;
	}

	public void setEmployee(Employee employee) {
		this.employee = employee;
	}

	public List<Employee> getEmployees() {
		if(FacesContext.getCurrentInstance().isPostback()){
			System.out.println(":: Postpack invocation :: Employees List is loaded from the cache ::");
		}
		else {
			System.out.println(":: Initial Invocation :: Employees List is loaded and returned ::");
		}
		return employees;
	}

	public void setEmployees(List<Employee> employees) {
		this.employees = employees;
	}

	@SuppressWarnings("unchecked")
	public String register() throws InterruptedException {
		this.service.getTransaction().begin();
		this.service.persist(employee);
		this.service.getTransaction().commit();
		this.employees = Lists.newArrayList(this.service.createQuery("select e from Employee e").getResultList());
		Thread.currentThread().sleep(800);
		this.employee = new Employee();
		return "";
	}
}

Before Highlighting Employees Table

After Highlighting Employees Table

Employee Registration Had Finished

4. ColumnToggler

Visibility of dataTable columns can be controlled through using of column Toggler component. Regardless of the location that you’ve positioned column Toggler component inside your Table, either inside the head of the table or in one of those columns you’ve defined.

Once you’ve trigger the toggler by clicking on the trigger itself (which might be command button) a list of all dataTable columns become seen for your visibility control. Just check those columns you would see and uncheck those you wouldn’t.

ColumnToggler component has provided two mandatory attributes you must define when it comes to be used.

  • Datasource (Table) in which the ColumnToggler component will get the columns ready for being controlled and the trigger by which the toggler get displayed for controlling.
  • The remaining attributes are just normal ones, idbinding and rendered.

Toggler Displaying Controls

Toggler Controlling Columns

As you’ve seen, by toggling the dataTable columns above, you are able to seeing/hiding what you want of those columns in a fancy, easy-peasy way. Look below at the implementation required for Primefaces view where the managed bean isn’t changed.

index.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:p="http://primefaces.org/ui">
	<h:head>
		<script name="jquery/jquery.js" library="primefaces"></script>
	</h:head>
	<f:view>
		<h:form prependId="false">
			<h2>JavaBeat Tutorials</h2>
			<h2>Primefaces + Column Toggler</h2>
			<div style="width: 700px;border: 1px;border-style: dotted;">
			<h:panelGrid columns="2">
				<h:outputText value="Enter Employee Name:"/>
				<p:inputText value="#{registrationManagedBean.employee.employeeName}"></p:inputText>
				<h:outputText value="Enter Employee Address Country:"/>
				<p:inputText value="#{registrationManagedBean.employee.address.addressCountry}"></p:inputText>
				<h:outputText value="Enter Employee Address City:"/>
				<p:inputText value="#{registrationManagedBean.employee.address.addressCity}"></p:inputText>
			</h:panelGrid>
			<p:commandButton value="Register" action="#{registrationManagedBean.register}" ajax="false"/>
			<p:separator/>
			<p:dataTable id="employeesSource" value="#{registrationManagedBean.employees}" var="employee">
			        <f:facet name="header">
			            Employees
			        	<p:commandButton id="toggler" type="button" value="Columns" style="float:right" icon="ui-icon-calculator" />
						<p:columnToggler datasource="employeesSource" trigger="toggler" />
			        </f:facet>
			        <p:column>
			        	<f:facet name="header">
			        		<p:outputLabel value="Employee Id"></p:outputLabel>
			        	</f:facet>
			        	<p:outputLabel value="#{employee.employeeId}"></p:outputLabel>
			        </p:column>
			        <p:column>
			        	<f:facet name="header">
			        		<p:outputLabel value="Employee Name"></p:outputLabel>
			        	</f:facet>
			        	<p:outputLabel value="#{employee.employeeName}"></p:outputLabel>
			        </p:column>
			        <p:column>
			        	<f:facet name="header">
			        		<p:outputLabel value="Employee's Address Country"></p:outputLabel>
			        	</f:facet>
			        	<p:outputLabel value="#{employee.address.addressCountry}"></p:outputLabel>
			        </p:column>
			        <p:column>
			        	<f:facet name="header">
			        		<p:outputLabel value="Employee's Address City"></p:outputLabel>
			        	</f:facet>
			        	<p:outputLabel value="#{employee.address.addressCity}"></p:outputLabel>
			        </p:column>
			</p:dataTable>
			</div>
		</h:form>
	</f:view>
</html>

5. Content Flow

Content flow is a horizontal content gallery component with a slide animation.

5.1 Content Flow Basic Info

ContentFlow - Basic Info

5.2 Content Flow Attributes

ContentFlow - Attributes

5.3 Content Flow Demo

ContentFlow requires content as children that can either be defined dynamically using iteration or one by one. Each item must have the content style class applied as well.

indexContentFlow.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:p="http://primefaces.org/ui">
	<h:head>
		<script name="jquery/jquery.js" library="primefaces"></script>
	</h:head>
	<f:view>
		<h:form prependId="false">
			<h2>JavaBeat Tutorials</h2>
			<h2>Primefaces + ContentFlow</h2>
			<p:outputPanel style="width: 700px;border: 1px;border-style: dotted;">
				<p:contentFlow id="contentFlow" value="#{imageView.images}" var="image">
				    <h:graphicImage url="/resources/images/Image-#{image}.jpg" styleClass="content"></h:graphicImage>
				</p:contentFlow>
			</p:outputPanel>
		</h:form>
	</f:view>
</html>

ImageView.java

package net.javabeat.primefaces.managedbeans;

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

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class ImageView {
	private List<String> images = new ArrayList<String>();

	public ImageView(){
		this.images.add("1");
		this.images.add("2");
	}

	public List<String> getImages() {
		return images;
	}

	public void setImages(List<String> images) {
		this.images = images;
	}
}

PrimeFaces 5 Project Structure

ContentFlow - Project Structure - Images Location

ContentFlow Demo

6. Persistence Entities

As per our explanation, we’ve introduced a JPA operations in our examples. These operations are done by a JPA entities and those entities are:

Address.java

package net.javabeat.jpa.data;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;

@Entity(name = "address")
public class Address {
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Integer addressId;
	private String addressCountry = "";
	private String addressCity = "";

	@OneToOne(cascade = CascadeType.ALL, mappedBy = "address")
	private Employee employee;

	public Employee getEmployee() {
		return employee;
	}

	public void setEmployee(Employee employee) {
		this.employee = employee;
	}

	public Integer getAddressId() {
		return addressId;
	}

	public void setAddressId(Integer addressId) {
		this.addressId = addressId;
	}

	public String getAddressCountry() {
		return addressCountry;
	}

	public void setAddressCountry(String addressCountry) {
		this.addressCountry = addressCountry;
	}

	public String getAddressCity() {
		return addressCity;
	}

	public void setAddressCity(String addressCity) {
		this.addressCity = addressCity;
	}
}

Employee.java

package net.javabeat.jpa.data;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;

@Entity
public class Employee {
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Integer employeeId;

	@Basic(optional = false)
	private String employeeName;

	@OneToOne(cascade = CascadeType.ALL)
	@JoinColumn(name = "Address")
	private Address address = new Address();

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	public Integer getEmployeeId() {
		return employeeId;
	}

	public void setEmployeeId(Integer employeeId) {
		this.employeeId = employeeId;
	}

	public String getEmployeeName() {
		return employeeName;
	}

	public void setEmployeeName(String employeeName) {
		this.employeeName = employeeName;
	}
}

7. Known issue

As you’ve seen, Primefaces content flow component doesn’t work for versions 5.0, 5.0.RC1, 5.0.RC2. We’ve opened a case at the Primefaces forums and this tutorial will be updated accordingly to the forum post.

8. Summary

Primefaces is one of the popular library for implementing JavaServer Faces UI. This tutorial has discussed most of the components introduced as part of the PrimeFaces 5. DataScroller, Cache, Spotlight, ColumnToggler and ContentFlow providing you a additional features in for UI design that your application may need.

Download Source Code for PrimeFaces 5

Comments

comments

About Amr Mohammed

Speak Your Mind

*