Welcome to Primefaces AccordionPanel example tutorial. Primefaces is the leading JSF implementation.
The excellent reputation Primefaces has gained is because of the dozens of UI components it provides . AccordionPanel is one of those components and it’s a container component that displays content in a stacked format.
This tutorial is intended to provide you the all required information and practices for dealing with the AccordionPanel component, even using of newly primefaces’s paradigm, which consists of employing a special JavaScript library object for controlling the component itself.
Primefaces AccordionPanel
It’s important for any developer has been coming into leveraging any of the primefaces component, know the basic information for the component being used. The basic information gives the developer information like the tag that would be used in the Primefaces page, the component type, class, family and all of renderer information required in case a customizing is targeted.
Per Primefaces itself, the basic information of AccordionPanel are:
Primefaces AccordionPanel Attributes
Unlike the basic information that you’ve got in the Basic info section, the attributes help the developer controlling the component by means of visibility, populating data, styling, triggering certain behaviors and others.
Per Primefaces, the all attributes are supported by AccordionPanel are:
After that brief description about the AccordionPanel, it’s the time to get started using it and knowing how it works and how could we leverage its attributes to serve the business case that we have. But before getting into, it’s important to know that the tutorial being implemented has been evolved using the maven archetype. In case you are familiar with, just skip the next section toward implementing the business scenario directly.
Create Project Using Eclipse IDE
You’ve already created your project using Eclipse IDE Dynamic Web Project, but from now you will learn basically a new way of creating a Maven Project through Eclipse IDE without the need to convert the Dynamic Web Project into Maven. It’s an easy-peasy way, so just follow:
- Make sure that you have installed Maven into your machine.
- From your Project Explorer RightClick – Select New – Project.
- Expand Maven node and select Maven Project and Click double Next.
- From all of those templates that Eclipse provided for you, makes sure that you are selected the line beneath groupId: org.apache.maven.archetypes and the artifactId: maven-archetype-webapp and click next.
- Enter your preferred groupId, artifactId, version and package and click finish.
Once you’ve finished the dialog, you are already got an Maven based project ready for your use. Before going forward into the next step, just makes sure that you have a java folder under your Java Resources, for doing that just do the following:
- Right Click Java Resources that located under the created project.
- Select New – Source Folder.
- Browse your project.
- Enter src/main/java inside Folder name.
- Click finish.
Your final structure looks like below
Setting Up Required Files and Dependencies
As Maven promised, the all dependencies required for your project for making it runnable must be located into your maven configuration file and it’s for sure the pom.xml.
For being the targeted application has used the primefaces library for which the jsf, jsp and servlet libraries are required, the form of the pom.xml should be:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.journaldev</groupId> <artifactId>Primefaces-AccordionPanel-Sample</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>Primefaces-AccordionPanel-Sample Maven Webapp</name> <url>https://maven.apache.org</url> <repositories> <repository> <id>prime-repo</id> <name>PrimeFaces Maven Repository</name> <url>https://repository.primefaces.org</url> <layout>default</layout> </repository> </repositories> <dependencies> <!-- Servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</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</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> </dependencies> </project> |
As for being the application uses the jsf framework, a set of needed lines should be added for making that framework running. Starting from the jsf listener – that should help the web container configure the jsf framework’s components like jsf custom components, validators and convertors that defined in the non required faces-config.xml or by using the annotations – ending with those required files like jsf framework properties, faces servlet and its mapping.
The whole work that you are located in the web.xml for establishing a full functional jsf isn’t far from what you would see below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xmlns:web="https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5" metadata-complete="true"> <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> <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>client</param-value> </context-param> <listener> <listener-class>com.sun.faces.config.ConfigureListener</listener-class> </listener> </web-app> |
You might want to ask, where is the faces-config.xml ? In fact and indeed, since the jsf 2, the faces-config.xml isn’t longer used, given hundred of annotations had covered the needed for defining the jsf component you may need. But for sure if you want to use it, it’s applicable and you have just add the following line into your web.xml file.
1 2 3 4 5 6 7 8 |
<context-param> <param-name>javax.faces.CONFIG_FILES</param-name> <param-value> /WEB-INF/faces-config.xml </param-value> </context-param> |
For now, you have established the jsf framework and the all libraries required for leveraging the Primefaces into your application. So, let’s start developing an application uses the AccordionPanel component.
For now, almost you are finished the all required steps for using the Primefaces 5 – AccordionPanel component, but one step just remaining.
As we knew, jsf 2 has obsoleted using of JSP (Java Server Pages) as view library, it’s now Facelets (XHTML Pages) that should comply with the XML well-formed principle.
Facelets library is already embedded in the jsf 2 dependencies and so, no need for adding a new libraries. For creating a new view using Facelets you shall follow the below steps:
- Right Click on the webapp folder.
- Select New – HTML File.
- Name your file as index and makes sure that the extension is xhtml & Click Next.
- Just finish the wizard.
By end of these steps, you will get an index.xhtml facelets page which will be updated accordingly for using the AccordionPanel. Just let’s your page like as below.
1 2 3 4 5 6 7 8 9 10 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml" xmlns:ui="https://java.sun.com/jsf/facelets" xmlns:h="https://java.sun.com/jsf/html" xmlns:f="https://java.sun.com/jsf/core" xmlns:p="https://primefaces.org/ui"> </html> |
Getting Started With Primefaces AccordionPanel
AccordionPanel consists of one or more tabs and each tab can group any content. Titles can also be defined with “title” facet. As a very simple using of AccordionPanel, you can consider the following lines as the minimal required code fragments for proper use of it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml" xmlns:ui="https://java.sun.com/jsf/facelets" xmlns:h="https://java.sun.com/jsf/html" xmlns:f="https://java.sun.com/jsf/core" xmlns:p="https://primefaces.org/ui"> <h:head> <script name="jquery/jquery.js" library="primefaces"></script> </h:head> <h:body> <div style="width: 500px;"> <p:accordionPanel activeIndex="0"> <p:tab title="Welcome Tab"> <p:outputLabel value="Welcome JournalDev !"></p:outputLabel> </p:tab> <p:tab title="Component Tab"> <p:outputLabel value="AccordionPanel Component !"></p:outputLabel> </p:tab> </p:accordionPanel> </div> </h:body> </html> |
Let’s analyze the above code for good understanding of it.
- Primefaces JavaScript library is mandatory line, cause the all components within Primefaces have used that library for rendering styles and executing client side behaviors.
- JSF 2 library, provides you the <h:head/> & <h:body/> for representing the header & body normal tags that are defined in the HTML.
- AccordionPanel component has defined in the page for containing two Tabs indexed starting from zero. The activeIndex attribute used for defining which Tabs from those defined should be displayed actively when the page get displayed. See AccordionPanel attributes section above.
As you’ve seen, AccordionPanel displays two different tabs in their respective order, they’re containing whatever content you wish. For being the activeIndex is zero by default, the first tab will be displayed once the page get shown. In case you’ve clicked on the Component Tab, the second tab will be displayed, while the Welcome Tab get closed.
If you’ve set activeIndex value equal to 1, Component Tab get displayed firstly.
Primefaces AccordionPanel – Dynamic Content Loading
AccordionPanel supports lazy loading of tab content, when dynamic attribute is set to true, only active tab contents will be rendered to the client side and clicking an inactive tab header will do an ajax request to load the tab contents.
This feature is useful to reduce bandwidth and speed up page loading time. By default activating a previously loaded dynamic tab does not initiate a request to load the contents again as tab is cached. To control this behavior use cache option.
For clarifying the dynamic concept, we’ve developed an AccordionPanelManagedBean that contains two String properties with their respective getter & setter.
For each tab within the accordionPanel, an outputPanel component has been defined and its value is associated with a one of those defined properties. In case the tab has been loaded, a print message should be printed. By default the loading of certain tab within AccordionPanel means that the contained components being rendered. The rendition process does affect calling of getter methods. Let’s see the impact of using dynamic and cache attributes.
Firstly, in case they’re never used, neither dynamic nor cache.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml" xmlns:ui="https://java.sun.com/jsf/facelets" xmlns:h="https://java.sun.com/jsf/html" xmlns:f="https://java.sun.com/jsf/core" xmlns:p="https://primefaces.org/ui"> <h:head> <script name="jquery/jquery.js" library="primefaces"></script> </h:head> <h:body> <div style="width: 500px;"> <p:accordionPanel activeIndex="0"> <p:tab title="Welcome Tab"> <p:outputLabel value="#{accordionPanelManagedBean.journalMessage}"></p:outputLabel> </p:tab> <p:tab title="Component Tab"> <p:outputLabel value="#{accordionPanelManagedBean.componentMessage}"></p:outputLabel> </p:tab> </p:accordionPanel> </div> </h:body> </html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.journaldev.primefaces.beans; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; @ManagedBean @SessionScoped public class AccordionPanelManagedBean { private String journalMessage = "Welcome JournalDev !"; private String componentMessage = "AccordionPanel Component !"; public String getJournalMessage() { System.out.println("Journal Message Loaded"); return journalMessage; } public void setJournalMessage(String journalMessage) { this.journalMessage = journalMessage; } public String getComponentMessage() { System.out.println("Component Message Loaded"); return componentMessage; } public void setComponentMessage(String componentMessage) { this.componentMessage = componentMessage; } } |
Where the resulted execution should be like this
So, the two tabs have been loaded even the active tab is set zero, that’s because the dynamic value was set false. At the other hand the cache attribute is set true, so any additional clicking on the tabs will not cause a new loading to be initiated. Even if you’ve changed the value cache to be true, without using of dynamic no changes might be noticed.
By adding the dynamic attribute into accordionPanel component with true value and keeping the cache with its default value. The result would be
Once the view get displayed. Now, when clicking the component tab the result should be
As you’ve noticed, component tab isn’t loaded until you cause that loading by clicking on. Any next coming clicking on that tabs will not cause the loading anymore, thus, no new messages may seen. If you would to see the messages at every time you’ve clicked, you shall override the default value of cache to be false with retaining the existence of dynamic.
The result of such that change should be
That’s expected, set cache value to be false, meaning that at every click, the content will be loaded instantly.
Primefaces AccordionPanel – Ajax Behavior Events
One of the most benefits that the jsf come with, is the ajax. Ajax has built into jsf lifecycle inherently, so for ajaxifying any component you would, you’ve just added the original f:ajax behavior into its tag. Primefaces 5 isn’t exceptional case, as it’s provided its own ajax behaviors using its own tag. For ajaxifying any of Primefaces 5 components that you would, you just need to provide p:ajax tag inside the component tag.
AccordionPanel is one of the primefaces component that leverage the concept of ajax, it provides you tabChange as a target behavior event that might be ajaxified. That event is executed when a tab is toggled.
For all ajax behaviors in Primefaces, a listener should be defined in the managed bean for listening the event behavior fired.
You can provide an tabChange ajax event by using the p:ajax while the listening could be done through defining a public void method that takes a TabChangeEvent as an argument. Just look at the followed example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml" xmlns:ui="https://java.sun.com/jsf/facelets" xmlns:h="https://java.sun.com/jsf/html" xmlns:f="https://java.sun.com/jsf/core" xmlns:p="https://primefaces.org/ui"> <h:head> <script name="jquery/jquery.js" library="primefaces"></script> </h:head> <h:body> <h:form> <div style="width: 500px;"> <p:accordionPanel activeIndex="0"> <p:ajax event="tabChange" listener="#{accordionPanelManagedBean.onChange}"></p:ajax> <p:tab title="Welcome Tab"> <p:outputLabel value="#{accordionPanelManagedBean.journalMessage}"></p:outputLabel> </p:tab> <p:tab title="Component Tab"> <p:outputLabel value="#{accordionPanelManagedBean.componentMessage}"></p:outputLabel> </p:tab> </p:accordionPanel> </div> </h:form> </h:body> </html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package com.journaldev.primefaces.beans; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import org.primefaces.event.TabChangeEvent; @ManagedBean @SessionScoped public class AccordionPanelManagedBean { private String journalMessage = "Welcome JournalDev !"; private String componentMessage = "AccordionPanel Component !"; public String getJournalMessage() { System.out.println("Journal Message Loaded"); return journalMessage; } public void setJournalMessage(String journalMessage) { this.journalMessage = journalMessage; } public String getComponentMessage() { System.out.println("Component Message Loaded"); return componentMessage; } public void setComponentMessage(String componentMessage) { this.componentMessage = componentMessage; } public void onChange(TabChangeEvent event) { System.out.println("Tab Changed :: You've Requested Seeing :: "+ event.getTab().getTitle()); } } |
Where the result of execution should be like below
Just one note should be noticed here, is that the ajax is a normal event that handled by the jsf lifecycle, thus it’s mandatory for you to put your component within an h:form and if you were missed it up, your ajax won’t fired and your listener isn’t invoked.
Primefaces AccordionPanel – Client Side API
Primefaces featured a new client side JavaScript API that’s used for make Primefaces’ components full functional plus the ability of controlling them through the PF object. PF is an implicit JavaScript object that provided by the Primefaces JavaScript API, it accepts a WidgetVar variable as a component argument as allowing the developer invoke component’s methods through it. Before Pimefaces 5, it was applicable for you to invoke the methods for a certain component through using the WidgetVar itself. Since Primefaces 4, using of WidgetVar variable directly has been deprecated and in the version 5 it’s removed totally.
Primefaces JavaScript library provides you two methods can be invoked against AccordionPanel component; select(index) and unselect(index). By passing the accordionPanel widgetVar into PF object, those provided methods are accessible there.
Look below, an example provided for AccordionPanel get controlled by using JavaScript library.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml" xmlns:ui="https://java.sun.com/jsf/facelets" xmlns:h="https://java.sun.com/jsf/html" xmlns:f="https://java.sun.com/jsf/core" xmlns:p="https://primefaces.org/ui"> <h:head> <script name="jquery/jquery.js" library="primefaces"></script> <script> alert(PF); function doSelect(index){ PF('accordionPanel').select(index); } function doUnSelect(index){ PF('accordionPanel').unselect(index); } </script> </h:head> <h:body> <h:form> <div style="width: 500px;"> <p:accordionPanel widgetVar="accordionPanel" activeIndex="0"> <p:ajax event="tabChange" listener="#{accordionPanelManagedBean.onChange}"></p:ajax> <p:tab title="Welcome Tab"> <p:outputLabel value="#{accordionPanelManagedBean.journalMessage}"></p:outputLabel> </p:tab> <p:tab title="Component Tab"> <p:outputLabel value="#{accordionPanelManagedBean.componentMessage}"></p:outputLabel> </p:tab> </p:accordionPanel> <input id="index" type="text"/> <input id="Select" value="Select" type="button" onclick="doSelect(document.getElementById('index').value);false"/> <input id="UnSelect" value="UnSelect" type="button" onclick="doUnSelect(document.getElementById('index').value);false"/> </div> </h:form> </h:body> </html> |
As being seen, we have two JavaScript actions invoke the select and unselect methods against AccordionPanel component.
Just put inside the number index you want, and see the the component does respond for your client side actions.
After finishing the tutorial, it’s good for you to see the all structure that the project reached into.
Primefaces AccordionPanel Summary
Primefaces 5 provides you dozens of ready made UI controls, one of them is the AccordionPanel. This tutorial has introduced the AccordionPanel component with all of its capabilities that might need when coming into using it. Download the sample project from below link and play around with it to learn more.