5. Inleiding tot de componentenbibliotheek PrimeFaces
5.1. De rol van PrimeFaces in een applicatie JSF
Laten we terugkeren naar de architectuur van een JSF-applicatie zoals we die aan het begin van dit document hebben besproken:
![]() |
De pagina’s JSF werden opgebouwd met drie tagbibliotheken:
- regel 2: de <h:x>-tags uit de naamruimte [http://java.sun.com/jsf/html] die overeenkomen met de HTML-tags,
- regel 3: de <f:y>-tags uit de naamruimte [http://java.sun.com/jsf/core] die overeenkomen met de tags JSF,
- regel 4: de <ui:z>-tags uit de naamruimte [http://java.sun.com/jsf/facelets] die overeenkomen met de facelet-tags.
Om de JSF-pagina’s te bouwen, voegen we een vierde tagbibliotheek toe, namelijk die van de PrimeFaces-componenten.
- regel 3: de <p:z>-tags uit de naamruimte [http://primefaces.org/ui] komen overeen met de PrimeFaces-componenten.
Dit is de enige wijziging die zichtbaar wordt. Deze verschijnt dus in de weergaven. De gebeurtenishandlers en de modellen blijven ongewijzigd ten opzichte van JSF. Dit is een belangrijk punt om te begrijpen.
Door het gebruik van PrimeFaces-componenten kunnen gebruiksvriendelijkere webinterfaces worden gecreëerd dankzij de vele componenten in deze bibliotheek, en vloeiendere interfaces dankzij de AJAX-technologie die deze bibliotheek standaard gebruikt. We spreken dan van rijke interfaces of RIA (Rich Internet Application).
De vorige JSF-architectuur wordt de volgende PF (PrimeFaces)-architectuur:
![]() |
5.2. De voordelen van Primefaces
De Primefaces-website [http://www.primefaces.org/showcase/ui/home.jsf] geeft een overzicht van de componenten die in een PF-pagina kunnen worden gebruikt:
![]() |
In de volgende voorbeelden zullen we de eerste twee functies van Primefaces gebruiken:
- sommige van de ongeveer honderd aangeboden componenten,
- het native gedrag AJAX daarvan.
Onder de aangeboden componenten bevinden zich:
![]() | ![]() | ![]() |
We zullen er in onze voorbeelden slechts een vijftiental gebruiken, maar dat is voldoende om de principes van het opbouwen van een Primefaces-pagina te begrijpen.
5.3. Primefaces leren
Primefaces biedt voorbeelden van het gebruik van elk van zijn componenten. Je hoeft alleen maar op de betreffende link te klikken. Laten we eens naar een voorbeeld kijken:
![]() |
- in [1], het voorbeeld voor de component [Spinner],
- in [2], het dialoogvenster dat verschijnt na een klik op de knop [Submit].
Er zijn hier drie nieuwigheden voor ons:
- de component [Spinner], die standaard niet bestaat in JSF,
- hetzelfde geldt voor het dialoogvenster,
- en ten slotte is de POST, die wordt geactiveerd door de [Submit], via AJAX geïmplementeerd. Als we de browser goed observeren tijdens de POST, zien we het zandloperpictogram niet. De pagina wordt niet opnieuw geladen. Ze wordt gewoon aangepast: er verschijnt een nieuw onderdeel, in dit geval het dialoogvenster, op de pagina.
Laten we eens kijken hoe dit allemaal tot stand komt. De code XHTML uit het voorbeeld is als volgt:
<h:form>
<p:panel header="Spinners">
<h:panelGrid id="grid" columns="2" cellpadding="5">
<h:outputLabel for="spinnerBasic" value="Basic Spinner: " />
<p:spinner id="spinnerBasic" value="#{spinnerController.number1}"/>
<h:outputLabel for="spinnerStep" value="Step Factor: " />
<p:spinner id="spinnerStep" value="#{spinnerController.number2}" stepFactor="0.25"/>
<h:outputLabel for="minmax" value="Min/Max: " />
<p:spinner id="minmax" value="#{spinnerController.number3}" min="0" max="100"/>
<h:outputLabel for="prefix" value="Prefix: " />
<p:spinner id="prefix" value="0" prefix="$" min="0" value="#{spinnerController.number4}"/>
<h:outputLabel for="ajaxspinner" value="Ajax Spinner: " />
<p:outputPanel>
<p:spinner id="ajaxspinner" value="#{spinnerController.number5}">
<p:ajax update="ajaxspinnervalue" process="@this" />
</p:spinner>
<h:outputText id="ajaxspinnervalue" value="#{spinnerController.number5}"/>
</p:outputPanel>
</h:panelGrid>
</p:panel>
<p:commandButton value="Submit" update="display" oncomplete="dialog.show()" />
<p:dialog header="Values" widgetVar="dialog" showEffect="fold" hideEffect="fold">
...
</p:dialog>
</h:form>
Laten we allereerst vaststellen dat er klassieke JSF-tags voorkomen: <h:form> op regel 1, <h:panelGrid> op regel 3, <h:outputLabel> op regel 4. Sommige JSF-tags worden overgenomen door PF en uitgebreid: <p:commandButton> regel 21. Vervolgens zijn er PF-tags voor opmaak: <p:panel> regel 2, <p:outputPanel> regel 13, <p:dialog> regel 23. Tot slot zijn er invoertags: <p:spinner> regel 5.
Laten we deze code analyseren aan de hand van de weergave:
![]() |
- in [1], de component die wordt verkregen met de tag <p:panel> op regel 2,
- in [2], het invoerveld dat wordt verkregen door de combinatie van een <p:outputLabel>-tag en <p:spinner>, regels 6 en 7,
- in [3], de knop van POST die is verkregen met de tag <p:commandButton> uit regel 21,
- in [4], het dialoogvenster van de regels 23-25,
- in [5], een onzichtbare container voor twee componenten. Deze wordt aangemaakt door de tag <p:outputPanel> op regel 13.
Laten we de volgende code analyseren die een actie AJAX implementeert:
<h:outputLabel for="ajaxspinner" value="Ajax Spinner: " />
<p:outputPanel>
<p:spinner id="ajaxspinner" value="#{spinnerController.number5}">
<p:ajax update="ajaxspinnervalue" process="@this" />
</p:spinner>
<h:outputText id="ajaxspinnervalue" value="#{spinnerController.number5}"/>
</p:outputPanel>
Deze code genereert de volgende weergave:
![]() |
- regel 1: geeft de tekst [1] weer. Dit is tegelijkertijd een label voor de component id=ajaxspinner (attribuut for). Deze component is die van regel 3 (attribuut id),
- regels 3-5: geven de component [2] weer. Deze component is een invoer-/weergavecomponent die is gekoppeld aan het model #{spinnerController.number5} (attribuut ‘value’),
- regel 6: geeft de component [3] weer. Deze component is een weergavecomponent die is gekoppeld aan het model #{spinnerController.number5} (attribuut value),
- regel 4: de tag <p:ajax> voegt een AJAX-gedrag toe aan de spinner. Telkens wanneer deze van waarde verandert, wordt een POST met deze waarde (attribuut process="@this") naar het model #{spinnerController.number5}. Vervolgens wordt de pagina bijgewerkt (attribuut update). Dit attribuut heeft als waarde de id van een component op de pagina, in dit geval die van regel 6. De component waarop het attribuut update betrekking heeft, wordt vervolgens bijgewerkt met het model. Dit is opnieuw #{spinnerController.number5}, dus de waarde van spinner. Zo volgt het veld [3] de invoer in het veld [2].
Dit is een AJAX-gedrag, een acroniem dat staat voor Asynchronous Javascript And XML. In het algemeen verloopt een AJAX-gedrag als volgt:
![]() |
- de browser geeft een HTML-pagina weer die JavaScript-code bevat (J van AJAX). De elementen van de pagina vormen een JavaScript-object dat het DOM (Document Object Model) wordt genoemd,
- de server host de webapplicatie die deze pagina heeft gegenereerd,
- in [1] vindt er een gebeurtenis plaats op de pagina. Bijvoorbeeld de incrementatie van spinner. Deze gebeurtenis wordt afgehandeld door JavaScript,
- In [2] voert het JavaScript een POST uit in de webapplicatie. Dit gebeurt asynchroon (de A van AJAX). De gebruiker kan gewoon doorgaan met de pagina. Deze is niet bevroren, maar kan indien nodig wel worden bevroren. De POST werkt het paginamodel bij op basis van de verzonden waarden, in dit geval het model #{spinnerController.number5},
- naar [3]. De webapplicatie stuurt vervolgens een antwoord terug naar JavaScript, namelijk XML (de X van AJAX) of JSON (JavaScript Object Notation),
- in [4] gebruikt het JavaScript dit antwoord om een specifiek veld van DOM bij te werken, in dit geval het veld van id=ajaxspinnervalue.
Bij gebruik van JSF en PrimeFaces wordt de JavaScript-code gegenereerd door PrimeFaces. Deze bibliotheek maakt gebruik van de JavaScript-bibliotheek JQuery. Evenzo zijn de PrimeFaces-componenten gebaseerd op die uit de componentenbibliotheek JQuery en UI (gebruikersinterface). JQuery vormt dus de basis van PrimeFaces.
Laten we terugkeren naar ons voorbeeld en nu de POST van de knop [Submit] bekijken:
![]() |
De code die bij POST hoort, is als volgt:
<p:commandButton value="Submit" update="display" oncomplete="dialog.show()" />
<p:dialog header="Values" widgetVar="dialog" showEffect="fold" hideEffect="fold">
<h:panelGrid id="display" columns="2" cellpadding="5">
<h:outputText value="Value 1: " />
<h:outputText value="#{spinnerController.number1}" />
<h:outputText value="Value 2: " />
<h:outputText value="#{spinnerController.number2}" />
<h:outputText value="Value 3: " />
<h:outputText value="#{spinnerController.number3}" />
<h:outputText value="Value 4: " />
<h:outputText value="#{spinnerController.number4}" />
<h:outputText value="Value 5: " />
<h:outputText value="#{spinnerController.number5}" />
</h:panelGrid>
</p:dialog>
</h:form>
- regel 1: de POST wordt geactiveerd door de knop op regel 1. In Primefaces roepen tags die een POST activeren, dit standaard op in de vorm van een AJAX-aanroep. Daarom hebben deze tags een update-attribuut om aan te geven welk veld moet worden bijgewerkt zodra het antwoord van de server is ontvangen. In dit geval is het bijgewerkte veld de panelGrid van regel 4. Dus zodra de POST terugkeert, wordt dit veld bijgewerkt met de waarden die naar het model zijn verzonden. Deze bevinden zich echter in een dialoogvenster dat standaard niet zichtbaar is. Het is het attribuut `oncomplete` in regel 1 dat het weergeeft. Deze gebeurtenis vindt plaats aan het einde van de verwerking van POST. De waarde van dit attribuut bestaat uit JavaScript-code. Hier wordt het dialoogvenster met id=dialog weergegeven, dus dat van regel 3 (attribuut widgetVar),
- regel 3: we zien verschillende attributen van het dialoogvenster. Je moet even experimenteren om te zien wat ze doen.
We hebben het model al genoemd, maar nog niet laten zien. Dit is het:
Over het algemeen kun je als volgt te werk gaan:
- zoek de PrimeFaces-component die je wilt gebruiken,
- bestudeer het bijbehorende voorbeeld. De voorbeelden van Primefaces zijn goed opgesteld en gemakkelijk te begrijpen.
5.4. Een eerste Primefaces-project: mv-pf-01
Laten we een Maven-webproject opzetten met NetBeans:
![]() |
- [1, 2, 3]: we maken een Maven-project van het type [Web Application],
![]() |
- [4]: de server wordt Tomcat,
- in [5], het gegenereerde project,
- in [6] verwijderen we het bestand [index.jsp] en het Java-pakket,
![]() |
- in [7, 8]: in de projecteigenschappen voegen we ondersteuning toe voor Java Server Faces,
![]() |
- in [9], en op het tabblad [Components] kiest men de PrimeFaces-componentbibliotheek. NetBeans biedt ondersteuning voor andere componentenbibliotheken: ICEFaces en RichFaces.
- In [10], het gegenereerde project. In [11] valt de afhankelijkheid van Primefaces op.
Kortom, een Primefaces-project is een klassiek JSF-project waaraan een afhankelijkheid van Primefaces is toegevoegd. Meer niet.
Nu we dit begrijpen, passen we het bestand [pom.xml] aan om met de nieuwste versies van de bibliotheken te kunnen werken:
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.1.8</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>3.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>jsf20</id>
<name>Repository for library Library[jsf20]</name>
<url>http://download.java.net/maven/2/</url>
</repository>
<repository>
<id>primefaces</id>
<name>Repository for library Library[primefaces]</name>
<url>http://repository.primefaces.org/</url>
</repository>
</repositories>
Let op de Maven-repository voor Primefaces in de regels 26-30. Nadat we deze wijzigingen hebben aangebracht, bouwen we het project om het downloaden van de afhankelijkheden te starten. We krijgen dan het project [12].
Laten we nu eens proberen het voorbeeld dat we hebben bestudeerd na te bootsen. De pagina [index.html] ziet er als volgt uit:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Spinner</title>
</h:head>
<h:body>
<!-- formulier -->
<h:form>
<p:panel header="Spinners">
<h:panelGrid id="grid" columns="2" cellpadding="5">
<h:outputLabel for="spinnerBasic" value="Basic Spinner: " />
<p:spinner id="spinnerBasic" value="#{spinnerController.number1}"/>
<h:outputLabel for="spinnerStep" value="Step Factor: " />
<p:spinner id="spinnerStep" value="#{spinnerController.number2}" stepFactor="0.25"/>
<h:outputLabel for="minmax" value="Min/Max: " />
<p:spinner id="minmax" value="#{spinnerController.number3}" min="0" max="100"/>
<h:outputLabel for="prefix" value="Prefix: " />
<p:spinner id="prefix" prefix="$" min="0" value="#{spinnerController.number4}"/>
<h:outputLabel for="ajaxspinner" value="Ajax Spinner: " />
<p:outputPanel>
<p:spinner id="ajaxspinner" value="#{spinnerController.number5}">
<p:ajax update="ajaxspinnervalue" process="@this" />
</p:spinner>
<h:outputText id="ajaxspinnervalue" value="#{spinnerController.number5}"/>
</p:outputPanel>
</h:panelGrid>
</p:panel>
<p:commandButton value="Submit" update="display" oncomplete="dialog.show()" />
<!-- dialoogvenster -->
<p:dialog header="Values" widgetVar="dialog" showEffect="fold" hideEffect="fold">
<h:panelGrid id="display" columns="2" cellpadding="5">
<h:outputText value="Value 1: " />
<h:outputText value="#{spinnerController.number1}" />
<h:outputText value="Value 2: " />
<h:outputText value="#{spinnerController.number2}" />
<h:outputText value="Value 3: " />
<h:outputText value="#{spinnerController.number3}" />
<h:outputText value="Value 4: " />
<h:outputText value="#{spinnerController.number4}" />
<h:outputText value="Value 5: " />
<h:outputText value="#{spinnerController.number5}" />
</h:panelGrid>
</p:dialog>
</h:form>
</h:body>
</html>
Vergeet niet regel 5, waarin de naamruimte van de Primefaces-tagbibliotheek wordt gedeclareerd. We voegen aan het project de bean toe die als sjabloon voor de pagina dient:
![]() |
De bean ziet er als volgt uit:
package beans;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.ManagedBean;
@ManagedBean
@RequestScoped
public class SpinnerController {
// sjabloon
private int number1;
private double number2;
private int number3;
private int number4;
private int number5;
// getters en setters
...
}
De klasse is een bean (regel 6) met een bereik op verzoek (regel 7). Aangezien er geen naam is opgegeven, krijgt de bean de naam van de klasse met het eerste letterteken in kleine letters: spinnerController.
Wanneer het project wordt uitgevoerd, krijg je het volgende:
![]() |
Zo hebben we zojuist laten zien hoe je een voorbeeld van de Primefaces-website kunt testen. Alle voorbeelden kunnen op deze manier worden getest.
Vervolgens zullen we ons alleen richten op bepaalde componenten van Primefaces. We zullen eerst de bestudeerde voorbeelden met JSF hernemen en bepaalde JSF-tags vervangen door Primefaces-tags. Het uiterlijk van de pagina’s zal enigszins veranderen; ze zullen zich gedragen als AJAX, maar de bijbehorende beans hoeven niet te worden aangepast. In elk van de volgende voorbeelden beperken we ons tot het presenteren van de XHTML-code van de pagina’s en de bijbehorende schermafbeeldingen. De lezer wordt uitgenodigd om de voorbeelden te testen om de verschillen tussen de JSF-pagina’s en de PF-pagina’s te ontdekken.
5.5. Voorbeeld mv-pf-02: gebeurtenisbeheerder – internationalisering – navigatie tussen pagina’s
Dit project is een port van het project JSF [mv-jsf2-02] (paragraaf 2.4, pagina 41):
![]() | ![]() |
Het NetBeans-project is als volgt:
![]() |
De pagina [index.html] ziet er als volgt uit:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<f:view locale="#{changeLocale.locale}">
<h:head>
<title><h:outputText value="#{msg['welcome.titre']}" /></title>
</h:head>
<body>
<h:form id="formulaire">
<h:panelGrid columns="2">
<p:commandLink value="#{msg['welcome.langue1']}" action="#{changeLocale.setFrenchLocale}" ajax="false"/>
<p:commandLink value="#{msg['welcome.langue2']}" action="#{changeLocale.setEnglishLocale}" ajax="false"/>
</h:panelGrid>
<h1><h:outputText value="#{msg['welcome.titre']}" /></h1>
<p:commandLink value="#{msg['welcome.page1']}" action="page1" ajax="false"/>
</h:form>
</body>
</f:view>
</html>
Op de regels 15, 16 en 19 zijn de tags <h:commandLink> vervangen door tags <p:commandLink>. Deze tag gedraagt zich standaard als AJAX, wat kan worden uitgeschakeld door het attribuut ajax="false" in te stellen. Hier gedragen de <p:commandLink>-tags zich dus als <h:commandLink>-tags: de pagina wordt opnieuw geladen wanneer op deze links wordt geklikt.
5.6. Voorbeeld mv-pf-03: pagina-indeling met behulp van facelets
Dit project toont het maken van XHTML-pagina’s met behulp van de facelets-sjablonen uit voorbeeld [mv-jsf2-09] (paragraaf 2.11):
![]() |
Het NetBeans-project is als volgt:
![]() |
- in [1], de configuratiebestanden van het project JSF,
- in [2], de pagina's in XHTML,
- in [3], de support-bean voor het wisselen van taal,
- in [4], de berichtbestanden,
- in [5], de afhankelijkheden.
De pagina’s van het project zijn gebaseerd op de pagina [layout.xhtml]:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<f:view locale="#{changeLocale.locale}">
<h:head>
<title>JSF</title>
<h:outputStylesheet library="css" name="styles.css"/>
</h:head>
<h:body style="background-image: url('${request.contextPath}/resources/images/standard.jpg');">
<h:form id="formulaire">
<table style="width: 600px">
<tr>
<td colspan="2" bgcolor="#ccccff">
<ui:include src="entete.xhtml"/>
</td>
</tr>
<tr>
<td style="width: 100px; height: 200px" bgcolor="#ffcccc">
<ui:include src="menu.xhtml"/>
</td>
<td>
<p:outputPanel id="contenu">
<ui:insert name="contenu" >
<h2>Contenu</h2>
</ui:insert>
</p:outputPanel>
</td>
</tr>
<tr bgcolor="#ffcc66">
<td colspan="2">
<ui:include src="basdepage.xhtml"/>
</td>
</tr>
</table>
</h:form>
</h:body>
</f:view>
</html>
- regel 9: een <f:view>-tag omvat de hele pagina om te profiteren van de internationalisering die deze mogelijk maakt,
- regel 15: een formulier met de id ‘form’. Dit formulier vormt de hoofdtekst van de pagina. In deze hoofdtekst is er slechts één dynamisch gedeelte, namelijk dat van de regels 28-30. Daar zal het variabele gedeelte van de pagina worden ingevoegd:
![]() |
- het hierboven omkaderd gebied wordt bijgewerkt door aanroepen van AJAX. Om het te identificeren, hebben we het opgenomen in een Primefaces-container die wordt gegenereerd door de tag <p:outputPanel> (regel 27). En deze container heeft de naam ‘contenu’ gekregen (id-attribuut). Aangezien deze zich in een formulier bevindt dat zelf een container met de naam ‘formulaire’ is, is de volledige naam van het dynamische gebied:formulaire:contenu. De eerste ‘:’ geeft aan dat we beginnen bij de root van het document, vervolgens naar de container met de naam ‘formulaire’ gaan en daarna naar de container met de naam ‘contenu’. Een moeilijkheid bij AJAX is het correct benoemen van de velden die moeten worden bijgewerkt via een aanroep van AJAX. Het eenvoudigste is om de broncode van de ontvangen pagina HTML te bekijken:
Hierboven zien we dat de tag <h:outputPanel> een tag HTML <span> heeft gegenereerd. In dit voorbeeld verwijzen zowel de relatieve naam formulaire:contenu (zonder de : aan het begin) als de volledige naam :formulaire:contenu (met de : aan het begin) naar hetzelfde object.
Let op: de aanroepen AJAX (<p:commandButton>, <p:commandLink>) die het dynamische gebied bijwerken, hebben het attribuut update=":formulaire:contenu".
De pagina [index.xhtml] is de enige pagina die door het project wordt weergegeven:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="layout.xhtml">
<ui:define name="contenu">
<ui:fragment rendered="#{requestScope.page1 || requestScope.page2==null}">
<ui:include src="page1.xhtml"/>
</ui:fragment>
<ui:fragment rendered="#{requestScope.page2}">
<ui:include src="page2.xhtml"/>
</ui:fragment>
</ui:define>
</ui:composition>
</html>
- regel 8: het sjabloon van [index.xhtml] is de zojuist gepresenteerde pagina [layout.xhtml],
- regel 9: dit is het veld met de inhoud-id dat wordt bijgewerkt door [index.html]. In dit veld bevinden zich twee fragmenten:
- het fragment [page1.xhtml], regel 11;
- het fragment [page2.xhtml] op regel 14.
Deze twee fragmenten sluiten elkaar uit.
- regel 10: het fragment [page1.xhtml] wordt weergegeven als het verzoek het attribuut page1 op true heeft staan of als het attribuut page2 niet bestaat. Dit is het geval bij het allereerste verzoek, waarbij geen van deze attributen in het verzoek aanwezig zal zijn. In dat geval wordt het fragment [page1.xhtml] weergegeven,
- regel 11; het fragment [page2.xhtml] wordt weergegeven als het attribuut page2 in de zoekopdracht op true staat
Het fragment [page1.xhtml] is als volgt:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<h:panelGrid columns="2">
<p:commandLink value="#{msg['page1.langue1']}" actionListener="#{changeLocale.setFrenchLocale}" ajax="true" update=":formulaire:contenu"/>
<p:commandLink value="#{msg['page1.langue2']}" actionListener="#{changeLocale.setEnglishLocale}" ajax="true" update=":formulaire:contenu"/>
</h:panelGrid>
<h1><h:outputText value="#{msg['page1.titre']}" /></h1>
<p:commandLink value="#{msg['page1.lien']}" update=":formulaire:contenu">
<f:setPropertyActionListener value="#{true}" target="#{requestScope.page2}" />
</p:commandLink>
</body>
</html>
en toont de volgende inhoud:
![]() |
- regels 11 en 12: de twee links om de taal te wijzigen. Deze twee links roepen de functie AJAX (ajax=true) aan. Dit is de standaardinstelling. Het attribuut ajax=true hoeft dus niet te worden opgegeven. We zullen dit verderop niet meer doen. Merk op dat deze twee links het gebied :formulier:inhoud (attribuut update) bijwerken, het gebied dat hierboven is omkaderd,
- regel 15: een navigatielink AJAX die ook hier het veld :formulier:inhoud bijwerkt,
- regel 16: we gebruiken de tag <h:setPropertyActionListener> om het attribuut page2 in de query op te nemen met de waarde true. Dit zorgt ervoor dat het fragment [page2.xhtml] (regel 6 hieronder) wordt weergegeven op de pagina [index.xhtml]:
<ui:composition template="layout.xhtml">
<ui:define name="contenu">
<ui:fragment rendered="#{requestScope.page1 || requestScope.page2==null}">
<ui:include src="page1.xhtml"/>
</ui:fragment>
<ui:fragment rendered="#{requestScope.page2}">
<ui:include src="page2.xhtml"/>
</ui:fragment>
</ui:define>
</ui:composition>
Het fragment [page2.xhtml] werkt op dezelfde manier:
![]() |
De code van [page2.xhtml] is als volgt:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<h1><h:outputText value="#{msg['page2.entete']}"/></h1>
<p:commandLink value="#{msg['page2.lien']}" update=":formulaire:contenu">
<f:setPropertyActionListener value="#{true}" target="#{requestScope.page1}" />
</p:commandLink>
</body>
</html>
Uit dit voorbeeld onthouden we de volgende punten voor verder gebruik:
- we zullen het sjabloon [layout.xhtml] gebruiken als sjabloon voor de pagina's,
- het dynamische gebied wordt aangeduid met de id:formulier:inhoud en wordt bijgewerkt door aanroepen van AJAX.
5.7. Voorbeeld mv-pf-04: invoerformulier
Dit project is een port van het project JSF2 [mv-jsf2-03] (zie paragraaf 2.5):
![]() |
Het NetBeans-project is als volgt:
![]() |
Hierboven, in [1], staan de pagina's XHTML van het project. De opmaak wordt verzorgd door het eerder besproken sjabloon [layout.xhtml]. De pagina [index.xhtml] is de enige pagina van het project. Deze wordt weergegeven in het gebied :formulier:inhoud. De code ervan is als volgt:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="layout.xhtml">
<ui:define name="contenu">
<ui:include src="page1.xhtml"/>
</ui:define>
</ui:composition>
</html>
Deze pagina geeft alleen het fragment [page1.xhtml] weer. Dit fragment komt overeen met het formulier dat in het voorbeeld [mv-jsf2-03] is besproken. Ter herinnering: dat formulier was bedoeld om de invoertags JSF te tonen. Deze tags zijn hier vervangen door Primefaces-tags.
PanelGrid
Om de elementen van [page1.xhtml] op te maken, gebruiken we de tag <p:panelGrid>. Bijvoorbeeld voor de twee taallinks:
<!-- talen -->
<p:panelGrid columns="2">
<p:commandLink value="#{msg['form.langue1']}" actionListener="#{changeLocale.setFrenchLocale}" update=":formulaire:contenu"/>
<p:commandLink value="#{msg['form.langue2']}" actionListener="#{changeLocale.setEnglishLocale}" update=":formulaire:contenu"/>
</p:panelGrid>
Dit levert de volgende weergave op:
Een andere vorm van de tag <p:panelGrid> is de volgende:
<p:panelGrid>
<f:facet name="header">
<p:row>
<p:column colspan="3"><h:outputText value="#{msg['form.titre']}"/></p:column>
</p:row>
<p:row>
<p:column><h:outputText value="#{msg['form.headerCol1']}"/></p:column>
<p:column><h:outputText value="#{msg['form.headerCol2']}"/></p:column>
<p:column><h:outputText value="#{msg['form.headerCol3']}"/></p:column>
</p:row>
</f:facet>
<p:row>
<p:column>
<h:outputText value="inputText"/>
</p:column>
<p:column>
<h:outputLabel for="inputText" value="#{msg['form.loginPrompt']}" />
<p:inputText id="inputText" value="#{form.inputText}"/>
</p:column>
<p:column>
<h:outputText id="inputTextValue" value="#{form.inputText}"/>
</p:column>
</p:row>
...
<f:facet name="footer">
<p:row>
<p:column colspan="3">
<div align="center">
<p:commandButton value="#{msg['form.submitText']}" update=":formulaire:contenu"/>
</div>
</p:column>
</p:row>
</f:facet>
</p:panelGrid>
De rijen en kolommen van de tabel worden aangeduid met de tags <p:row> en <p:column>.
De regels 3-12 definiëren de koptekst van de tabel:
De regels 14-25 definiëren een rij van de tabel:
De regels 27-35 definiëren de voettekst van de tabel:
inputText
<p:row>
<p:column>
<h:outputText value="inputText"/>
</p:column>
<p:column>
<h:outputLabel for="inputText" value="#{msg['form.loginPrompt']}" />
<p:inputText id="inputText" value="#{form.inputText}"/>
</p:column>
<p:column>
<h:outputText id="inputTextValue" value="#{form.inputText}"/>
</p:column>
</p:row>
password
<p:row>
<p:column>
<h:outputText value="inputSecret"/>
</p:column>
<p:column>
<h:outputLabel for="inputSecret" value="#{msg['form.passwdPrompt']}"/>
<p:password id="inputSecret" value="#{form.inputSecret}" feedback="true"
promptLabel="#{msg['form.promptLabel']}" weakLabel="#{msg['form.weakLabel']}"
goodLabel="#{msg['form.goodLabel']}" strongLabel="#{msg['form.strongLabel']}" />
</p:column>
<p:column>
<h:outputText id="inputSecretValue" value="#{form.inputSecret}"/>
</p:column>
</p:row>
![]() |
Op regel 7 zorgt het attribuut feedback=true ervoor dat er feedback wordt gegeven over de kwaliteit [1] van het wachtwoord.
inputTextArea
<p:row>
<p:column>
<h:outputText value="inputTextArea"/>
</p:column>
<p:column>
<h:outputLabel for="inputTextArea" value="#{msg['form.descPrompt']}"/>
<p:editor id="inputTextArea" value="#{form.inputTextArea}" rows="4"/>
</p:column>
<p:column>
<h:outputText id="inputTextAreaValue" value="#{form.inputTextArea}"/>
</p:column>
</p:row>
![]() |
Regel 7: de tag <p:editor> toont een rich-editor waarmee de tekst kan worden opgemaakt (lettertype, grootte, kleur, uitlijning, ...). Wat naar de server wordt verzonden, is de code HTML van de ingevoerde tekst [2].
selectOneListBox
<p:row>
<p:column>
<h:outputText value="selectOneListBox"/>
</p:column>
<p:column>
<h:outputLabel for="selectOneListBox1" value="#{msg['form.selectOneListBox1Prompt']}"/>
<p:selectOneListbox id="selectOneListBox1" value="#{form.selectOneListBox1}">
<f:selectItem itemValue="1" itemLabel="un"/>
<f:selectItem itemValue="2" itemLabel="deux"/>
<f:selectItem itemValue="3" itemLabel="trois"/>
</p:selectOneListbox>
</p:column>
<p:column>
<h:outputText id="selectOneListBox1Value" value="#{form.selectOneListBox1}"/>
</p:column>
</p:row>
![]() |
selectOneMenu
<p:row>
<p:column>
<h:outputText value="selectOneMenu"/>
</p:column>
<p:column>
<h:outputLabel for="selectOneMenu" value="#{msg['form.selectOneMenuPrompt']}"/>
<p:selectOneMenu id="selectOneMenu" value="#{form.selectOneMenu}">
<f:selectItem itemValue="1" itemLabel="un"/>
<f:selectItem itemValue="2" itemLabel="deux"/>
<f:selectItem itemValue="3" itemLabel="trois"/>
<f:selectItem itemValue="4" itemLabel="quatre"/>
<f:selectItem itemValue="5" itemLabel="cinq"/>
</p:selectOneMenu>
</p:column>
<p:column>
<h:outputText id="selectOneMenuValue" value="#{form.selectOneMenu}"/>
</p:column>
</p:row>
![]() |
selectManyMenu
<p:row>
<p:column>
<h:outputText value="selectManyMenu"/>
</p:column>
<p:column>
<h:outputLabel for="selectManyMenu" value="#{msg['form.selectManyMenuPrompt']}"/>
<p:selectManyMenu id="selectManyMenu" value="#{form.selectManyMenu}" >
<f:selectItem itemValue="1" itemLabel="un"/>
<f:selectItem itemValue="2" itemLabel="deux"/>
<f:selectItem itemValue="3" itemLabel="trois"/>
<f:selectItem itemValue="4" itemLabel="quatre"/>
<f:selectItem itemValue="5" itemLabel="cinq"/>
</p:selectManyMenu>
<p:commandLink value="#{msg['form.buttonRazText']}" actionListener="#{form.clearSelectManyMenu()}" update=":formulaire:selectManyMenu" style="margin-left: 10px"/>
</p:column>
<p:column>
<h:outputText id="selectManyMenuValue" value="#{form.selectManyMenuValue}"/>
</p:column>
</p:row>
![]() |
In regel 14 valt op dat de koppeling [Raz] een update uitvoert (AJAX) van het veld :formulier:selectManyMenu, dat overeenkomt met de component in regel 6. Men moet echter weten dat tijdens de POST AJAX alle waarden van het formulier worden verzonden. Het is dus het volledige model dat wordt bijgewerkt. Met dit model wordt echter alleen het veld :formulier:selectManyMenu bijgewerkt.
selectBooleanCheckbox
<p:row>
<p:column>
<h:outputText value="selectBooleanCheckbox"/>
</p:column>
<p:column>
<h:outputLabel for="selectBooleanCheckbox" value="#{msg['form.selectBooleanCheckboxPrompt']}"/>
<p:selectBooleanCheckbox id="selectBooleanCheckbox" value="#{form.selectBooleanCheckbox}"/>
</p:column>
<p:column>
<h:outputText id="selectBooleanCheckboxValue" value="#{form.selectBooleanCheckbox}"/>
</p:column>
</p:row>
selectManyCheckbox
<p:row>
<p:column>
<h:outputText value="selectManyCheckbox"/>
</p:column>
<p:column>
<h:outputLabel for="selectManyCheckbox" value="#{msg['form.selectManyCheckboxPrompt']}"/>
<p:selectManyCheckbox id="selectManyCheckbox" value="#{form.selectManyCheckbox}">
<f:selectItem itemValue="1" itemLabel="rouge"/>
<f:selectItem itemValue="2" itemLabel="bleu"/>
<f:selectItem itemValue="3" itemLabel="blanc"/>
<f:selectItem itemValue="4" itemLabel="noir"/>
</p:selectManyCheckbox>
</p:column>
<p:column>
<h:outputText id="selectManyCheckboxValue" value="#{form.selectManyCheckboxValue}"/>
</p:column>
</p:row>
selectOneRadio
<p:row>
<p:column>
<h:outputText value="selectOneRadio"/>
</p:column>
<p:column>
<h:outputLabel for="selectOneRadio" value="#{msg['form.selectOneRadioPrompt']}"/>
<p:selectOneRadio id="selectOneRadio" value="#{form.selectOneRadio}" >
<f:selectItem itemValue="1" itemLabel="voiture"/>
<f:selectItem itemValue="2" itemLabel="vélo"/>
<f:selectItem itemValue="3" itemLabel="scooter"/>
<f:selectItem itemValue="4" itemLabel="marche"/>
</p:selectOneRadio>
</p:column>
<p:column>
<h:outputText id="selectOneRadioValue" value="#{form.selectOneRadio}"/>
</p:column>
</p:row>
5.8. Voorbeeld: mv-pf-05: dynamische lijsten
Dit project is een port van het project JSF2 [mv-jsf2-04] (zie paragraaf 2.6):

Dit project voegt geen nieuwe PrimeFaces-tags toe ten opzichte van het vorige project. Daarom zullen we er geen commentaar op geven. Het maakt deel uit van de lijst met voorbeelden die op de website van het document ter beschikking worden gesteld aan de lezer.
5.9. Voorbeeld: mv-pf-06: navigatie – sessie – uitzonderingsafhandeling
Dit project is een port van het project JSF2 [mv-jsf2-05] (zie paragraaf 2.7):
![]() |
Ook dit voorbeeld introduceert geen nieuwe PrimeFaces-tags. We zullen alleen ingaan op de hierboven omkaderde tabel met links:
<p:panelGrid columns="6">
<p:commandLink value="1" action="form1?faces-redirect=true" ajax="false"/>
<p:commandLink value="2" action="#{form.doAction2}" ajax="false"/>
<p:commandLink value="3" action="form3?faces-redirect=true" ajax="false"/>
<p:commandLink value="4" action="#{form.doAction4}" ajax="false"/>
<p:commandLink value="#{msg['form.pagealeatoireLink']}" action="#{form.doAlea}" ajax="false"/>
<p:commandLink value="#{msg['form.exceptionLink']}" action="#{form.throwException}" ajax="false"/>
</p:panelGrid>
- alle links hebben het attribuut ajax=false. De pagina wordt dus op de normale manier geladen,
- let op regels 2 en 4, waar te zien is hoe een omleiding wordt uitgevoerd.
5.10. Voorbeeld: mv-pf-07: validatie en conversie van invoer
Dit project is de port naar het project JSF2 [mv-jsf2-06] (zie paragraaf 2.8):

De applicatie introduceert twee nieuwe tags, de tag <p:messages>:
<p:messages globalOnly="true"/>

en de tag <p:message>:
<p:inputText id="saisie1" value="#{form.saisie1}" styleClass="saisie"/>
<p:message for="saisie1" styleClass="error"/>
In vergelijking met de tag <h:message> van JSF brengt de tag <p:message> van PF de volgende wijzigingen met zich mee:
- de foutmelding ziet er anders uit ([1]),
- het veld met de foutieve invoer is omgeven door een rood kader in [2].
5.11. Voorbeeld: mv-pf-08: gebeurtenissen die verband houden met de statuswijziging van componenten
Dit project is de port naar het project JSF2 [mv-jsf2-07] (zie paragraaf 2.9):

Het project JSF introduceerde het concept van listeners. Het beheer van listener met Primefaces werd op een andere manier uitgevoerd.
Met JSF:
Met Primefaces:
- regel 2: de tag <h:selectOneMenu> zonder het attribuut valueChangeListener,
- regel 4: de tag <p:ajax> voegt een gedrag AJAX toe aan de bovenliggende tag <h:selectOneMenu>. Standaard reageert deze op de gebeurtenis "waardeverandering" van de lijst combo1. Bij deze gebeurtenis worden de waarden van het formulier waartoe de tag behoort via een AJAX-aanroep naar de server verzonden. Het model wordt dus bijgewerkt. Dit nieuwe model wordt gebruikt om de keuzelijst met ID combo2 (regel 10) bij te werken. Merk op, in regel 4, dat de aanroep AJAX geen methode van het model uitvoert. Dat is hier niet nodig. We willen het model gewoon wijzigen via POST op basis van de ingevoerde waarden.
5.12. Voorbeeld: mv-pf-09: geassisteerde invoer
Dit project bevat Primefaces-specifieke invoertags die het invoeren van bepaalde soorten gegevens vergemakkelijken:
![]() |
5.12.1. Het NetBeans-project
Het NetBeans-project ziet er als volgt uit:
![]() |
Het belang van het project ligt in:
- de enige pagina [index.html] die door het project wordt weergegeven,
- het sjabloon [Form.java] van die pagina.
5.12.2. Het sjabloon
Het formulier bevat vier invoervelden die gekoppeld zijn aan het volgende sjabloon:
package forms;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.ManagedBean;
@ManagedBean
@SessionScoped
public class Form implements Serializable {
private Date calendrier;
private Integer slider = 100;
private Integer spinner = 1;
private String autocompleteValue;
public Form() {
}
public List<String> autocomplete(String query) {
...
}
// getters en setters
...
}
De vier invoervelden zijn gekoppeld aan de velden in de regels 14-17.
5.12.3. Het formulier
Het formulier ziet er als volgt uit:
<?xml version='1.0' encoding='UTF-8' ?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="layout.xhtml">
<ui:define name="contenu">
<h2><h:outputText value="#{msg['app.titre']}"/></h2>
<p:growl id="messages" autoUpdate="true"/>
<p:panelGrid columns="3" columnClasses="col1,col2,col3,col4">
<h:outputText value="#{msg['saisie.type']}" styleClass="entete"/>
<h:outputText value="#{msg['saisie.champ']}" styleClass="entete"/>
<h:outputText value="#{msg['bean.valeur']}" styleClass="entete"/>
<!-- kalender -->
...
<!-- schuifbalk -->
...
<!-- spinner -->
...
<!-- autocomplete -->
...
</p:panelGrid>
</ui:define>
</ui:composition>
</html>
Laten we de vier invoervelden eens bekijken.
5.12.4. De kalender
Met de tag <p:calendar> kun je een datum selecteren uit een kalender. Deze tag ondersteunt verschillende attributen.
<h:outputText value="#{msg['calendar.prompt']}"/>
<p:calendar id="calendrier" value="#{form.calendrier}" pattern="dd/MM/yyyy" timeZone="Europe/Paris"/>
<h:outputText id="calendrierValue" value="#{form.calendrier}">
<f:convertDateTime pattern="dd/MM/yyyy" type="date" timeZone="Europe/Paris"/>
</h:outputText>
Op regel 2 wordt aangegeven dat de datum moet worden weergegeven in het formaat „dd/mm/jjjj“ en dat de tijdzone die van Parijs is. Wanneer de cursor in het invoerveld wordt geplaatst, wordt een kalender weergegeven:
![]() |
5.12.5. De schuifbalk
Met de tag <p:slider> kun je een geheel getal invoeren door een schuifbalk langs een balk te verschuiven:
De code van de tag is als volgt:
<h:outputText value="#{msg['slider.prompt']}"/>
<h:panelGrid columns="1" style="margin-bottom:10px">
<p:inputText id="slider" value="#{form.slider}" required="true" requiredMessage="#{msg['slider.required']}" validatorMessage="#{msg['slider.invalide']}">
<f:validateLongRange minimum="100" maximum="200"/>
</p:inputText>
<p:slider for="slider" minValue="100" maxValue="200"/>
</h:panelGrid>
<h:outputText id="sliderValue" value="#{form.slider}"/>
- regel 3: hier staat een standaard <p:inputText>-tag waarmee het gehele getal kan worden ingevoerd. Dit getal kan ook via de schuifbalk worden ingevoerd,
- regel 4: de tag <p:slider> is gekoppeld aan de invoertag <p:inputText> (attribuut for). Hiervoor worden een minimum- en een maximumwaarde ingesteld.
5.12.6. De spinner
We hebben deze component al eerder besproken:
<h:outputText value="#{msg['spinner.prompt']}"/>
<p:spinner id="spinner" min="1" max="12" value="#{form.spinner}" required="true" requiredMessage="#{msg['spinner.required']}" validatorMessage="#{msg['spinner.invalide']}">
<f:validateLongRange minimum="1" maximum="12"/>
</p:spinner>
<h:outputText id="spinnerValue" value="#{form.spinner}"/>
Regel 3: met de spinner kan een geheel getal tussen 1 en 12 worden ingevoerd. Het getal kan rechtstreeks in het invoerveld van de spinner worden ingevoerd of met de pijltjes worden verhoogd of verlaagd.
5.12.7. Geassisteerde invoer
Bij de ingangsondersteuning typt u de eerste tekens van de invoer. Er verschijnen dan suggesties in een vervolgkeuzelijst. Je kunt er een selecteren. Deze component wordt gebruikt in plaats van vervolgkeuzelijsten wanneer deze te veel inhoud bevatten. Stel dat je een vervolgkeuzelijst met steden in Frankrijk wilt aanbieden. Dat zijn er enkele duizenden. Als je de gebruiker de eerste drie tekens van de stad laat typen, kun je hem vervolgens een beperkte lijst aanbieden met steden die daarmee beginnen.
![]() |
De code van deze component is als volgt:
<h:outputText value="#{msg['autocomplete.prompt']}"/>
<p:autoComplete value="#{form.autocompleteValue}" completeMethod="#{form.autocomplete}" required="true" requiredMessage="#{msg['autocomplete.required']}"/>
<h:outputText id="autocompleteValue" value="#{form.autocompleteValue}"/>
<h:panelGroup/>
<h:panelGroup>
<center><p:commandLink value="#{msg['valider']}" update="formulaire:contenu"/></center>
</h:panelGroup>
<h:panelGroup/>
De tag <p:autoComplete> op regel 2 zorgt voor de invoerhulp. De parameter die ons hier interesseert, is het attribuut completeMethod, waarvan de waarde de naam is van een methode in het model die verantwoordelijk is voor het doen van voorstellen die overeenkomen met de door de gebruiker ingevoerde tekens. Deze methode is hier de volgende:
public List<String> autocomplete(String query) {
List<String> results = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
results.add(query + i);
}
return results;
}
- regel 1: de methode ontvangt als parameter de tekenreeks die de gebruiker in het invoerveld heeft getypt. Ze retourneert een lijst met suggesties,
- regels 4-6: er wordt een lijst van 10 suggesties samengesteld die de als parameter ontvangen tekens bevat en daar een cijfer van 0 tot 9 aan toevoegt.
5.12.8. De tag <p:growl>
De tag <p:growl> is een mogelijk alternatief voor de tag <p:messages>, die foutmeldingen van het formulier weergeeft.
<p:growl id="messages" autoUpdate="true"/>
Hierboven wordt het id-attribuut niet gebruikt. Het attribuut autoUpdate=true geeft aan dat de lijst met foutmeldingen bij elke POST van het formulier moet worden vernieuwd.
Stel dat we het volgende formulier valideren: [1]:
![]() |
- in [2], dan geeft de tag <p:growl> de foutmeldingen weer die bij de foutieve invoer horen.
5.13. Voorbeeld: mv-pf-10: dataTable - 1
Dit project presenteert de tag <p:dataTable>, die wordt gebruikt om lijsten met gegevens weer te geven

5.13.1. Het NetBeans-project
Het NetBeans-project ziet er als volgt uit:
![]() |
Het belang van het project ligt in:
- de enige pagina [index.html] die door het project wordt weergegeven,
- het model [Form.java] van deze pagina en de bean [Personne].
5.13.2. Het berichtenbestand
Het bestand [messages_fr.properties] ziet er als volgt uit:
app.titre=intro-08
app.titre2=DataTable - 1
submit=Valider
personnes.headers.id=Id
personnes.headers.nom=Nom
personnes.headers.prenom=Pr\u00e9nom
layout.hautdepage=Primefaces en fran\u00e7ais
layout.menu=Menu fran\u00e7ais
layout.basdepage=ISTIA, universit\u00e9 d'Angers
form.langue1=Fran\u00e7ais
form.langue2=Anglais
form.noData=La liste des personnes est vide
form.listePersonnes=Liste de personnes
form.action=Action
5.13.3. Het model
De bean [Personne] vertegenwoordigt een persoon:
package forms;
import java.io.Serializable;
public class Personne implements Serializable{
// gegevens
private int id;
private String nom;
private String prénom;
// fabrikanten
public Personne(){
}
public Personne(int id, String nom, String prénom){
this.id=id;
this.nom=nom;
this.prénom=prénom;
}
// toString
public String toString(){
return String.format("Personne[%d,%s,%s]", id,nom,prénom);
}
// getters en setters
...
}
Het sjabloon van de pagina [index.xhtml] is de volgende klasse [Form]:
package forms;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class Form implements Serializable{
// model
private List<Personne> personnes;
private int personneId;
// constructor
public Form() {
// initialisatie van de lijst met personen
personnes = new ArrayList<Personne>();
personnes.add(new Personne(1, "dupont", "jacques"));
personnes.add(new Personne(2, "durand", "élise"));
personnes.add(new Personne(3, "martin", "jacqueline"));
}
public void retirerPersonne() {
...
}
// getters en setters
...
}
- regels 9-10: de bean heeft een sessiebereik,
- regels 18-24: de constructor maakt een lijst van drie personen aan, een lijst die dus tijdens de verzoeken blijft bestaan,
- regel 15: het nummer van een persoon die uit de lijst moet worden verwijderd,
- regels 26-28: de methode voor het verwijderen.
5.13.4. Het formulier
Het formulier is het volgende: [index.xhtml]:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="layout.xhtml">
<ui:define name="contenu">
<h2><h:outputText value="#{msg['app.titre2']}"/></h2>
<p:dataTable value="#{form.personnes}" var="personne" emptyMessage="#{msg['form.noData']}">
<f:facet name="header">
#{msg['form.listePersonnes']}
</f:facet>
<p:column>
<f:facet name="header">
#{msg['personnes.headers.id']}
</f:facet>
#{personne.id}
</p:column>
<p:column>
<f:facet name="header">
#{msg['personnes.headers.nom']}
</f:facet>
#{personne.nom}
</p:column>
<p:column>
<f:facet name="header">
#{msg['personnes.headers.prenom']}
</f:facet>
#{personne.prénom}
</p:column>
<p:column>
<f:facet name="header">
#{msg['form.action']}
</f:facet>
<p:commandLink value="Retirer" action="#{form.retirerPersonne}" update=":formulaire:contenu">
<f:setPropertyActionListener target="#{form.personneId}" value="#{personne.id}"/>
</p:commandLink>
</p:column>
</p:dataTable>
</ui:define>
</ui:composition>
</html>
Dit levert het volgende scherm op (zie kader hieronder):
![]() |
- regel 12: genereert de hierboven omkaderde tabel. Het attribuut value verwijst naar de verzameling die door de tabel wordt weergegeven, in dit geval de lijst met personen uit het model. Het attribuut emptyMessage is optioneel. Het verwijst naar het bericht dat moet worden weergegeven wanneer de lijst leeg is. Standaard is dit 'no records found'. Hier zal dit zijn:
![]() |
- regels 13-15: genereren de koptekst [1],
- regels 16-21: genereren de kolom [2],
- regels 22-27: genereren de kolom [3],
- regels 28-33: genereren de kolom [4],
- regels 34-41: genereren de kolom [5].
Via de link [Retirer] kan een persoon uit de lijst worden verwijderd. Regel [38]: dit wordt uitgevoerd door de methode [Form].retirerPersonne. Deze methode moet het nummer kennen van de persoon die moet worden verwijderd. Dit nummer wordt in regel 39 doorgegeven. In regel 38 is het attribuut ‘action’ gebruikt. Bij andere gelegenheden is het attribuut actionListener gebruikt. Ik ben er niet helemaal zeker van of ik het functionele verschil tussen deze twee attributen goed begrijp. In de praktijk valt echter op dat de attributen die worden ingesteld door de tags <setPropertyActionListener> worden ingesteld vóór de uitvoering van de methode die door het attribuut ‘action’ wordt aangeduid, en dat dit niet het geval is voor het attribuut actionListener. Kortom: zodra er parameters moeten worden doorgegeven aan de aangeroepen actie, moet het attribuut action worden gebruikt.
De methode om een persoon te verwijderen is als volgt:
...
@ManagedBean
@SessionScoped
public class Form implements Serializable{
// model
private List<Personne> personnes;
private int personneId;
public void retirerPersonne() {
// de geselecteerde persoon wordt gezocht
int i = 0;
for (Personne personne : personnes) {
// huidige persoon = geselecteerde persoon?
if (personne.getId() == personneId) {
// de huidige persoon wordt uit de lijst verwijderd
personnes.remove(i);
// klaar
break;
} else {
// volgende persoon
i++;
}
}
}
...
}
5.14. Voorbeeld: mv-pf-11: dataTable - 2
Dit project toont een tabel met een lijst met gegevens waarin een rij kan worden geselecteerd:
![]() |
Wanneer een rij uit de tabel wordt geselecteerd, wordt op het moment van de POST informatie over de geselecteerde rij naar het model verzonden. Daardoor is er niet langer een [Retirer]-koppeling per persoon nodig. Eén enkele koppeling voor de gehele tabel volstaat.
Het NetBeans-project is op enkele details na identiek aan het vorige: het formulier en het bijbehorende model. Het formulier [index.xhtml] ziet er als volgt uit:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="layout.xhtml">
<ui:define name="contenu">
<h2><h:outputText value="#{msg['app.titre2']}"/></h2>
<p:dataTable value="#{form.personnes}" var="personne" emptyMessage="#{msg['form.noData']}"
rowKey="#{personne.id}" selection="#{form.personneChoisie}" selectionMode="single">
...
</p:dataTable>
<p:commandLink value="Retirer" action="#{form.retirerPersonne}" update=":formulaire:contenu"/>
</ui:define>
</ui:composition>
</html>
- regel 13: met het attribuut selectionMode kan een selectiemodus worden gekozen: single of multiple. Hier hebben we ervoor gekozen om slechts één regel te selecteren,
- regel 13: het attribuut rowkey verwijst naar een attribuut van de weergegeven elementen waarmee deze op unieke wijze kunnen worden geselecteerd. Hier hebben we de id van de geselecteerde persoon gekozen,
- regel 13: het attribuut selection verwijst naar het attribuut van het model dat een verwijzing naar de geselecteerde persoon zal ontvangen. Dankzij het voorgaande rowkey-attribuut kan aan de serverzijde een verwijzing naar de geselecteerde persoon worden berekend. We beschikken niet over de details van de gebruikte methode. We kunnen ons voorstellen dat de verzameling sequentieel wordt doorlopen op zoek naar het element dat overeenkomt met de geselecteerde rowkey. Dit betekent dat als de methode die rowkey aan selection koppelt complexer is, deze methode niet bruikbaar is,
Dit uitgelegd, evolueert de methode [Form].retirerPersonne als volgt:
...
@ManagedBean
@SessionScoped
public class Form implements Serializable {
// sjabloon
private List<Personne> personnes;
private Personne personneChoisie;
// fabrikant
public Form() {
...
}
public void retirerPersonne() {
// de geselecteerde persoon wordt verwijderd
personnes.remove(personneChoisie);
}
// getters en setters
...
}
- regel 9: bij elke POST wordt de verwijzing op regel 9 geïnitialiseerd met de verwijzing, in de lijst op regel 8, naar de geselecteerde persoon,
- in 18: het verwijderen van de persoon wordt hierdoor vereenvoudigd. De zoekopdracht die we in het vorige voorbeeld hadden uitgevoerd, werd gedaan met de tag <dataTable>.
5.15. Voorbeeld: mv-pf-12: dataTable - 3
Dit project is vergelijkbaar met het vorige. Met name de weergave is identiek:

Het NetBeans-project is identiek aan het vorige, op enkele details na die we hieronder zullen bespreken. Het formulier [index.xhtml] ziet er als volgt uit:
...
<ui:composition template="layout.xhtml">
<ui:define name="contenu">
<h2><h:outputText value="#{msg['app.titre2']}"/></h2>
<p:dataTable value="#{form.personnes}" var="personne" emptyMessage="#{msg['form.noData']}"
selectionMode="single" selection="#{form.personneChoisie}">
...
</p:dataTable>
<p:commandLink value="Retirer" action="#{form.retirerPersonne}" update=":formulaire:contenu"/>
</ui:define>
</ui:composition>
</html>
- In regel 6 is het attribuut `rowkey` verdwenen, het attribuut `selection` blijft bestaan. De koppeling tussen de attributen `rowkey` en `selection` verloopt nu via een klasse. Het attribuut value in regel 5 heeft nu als waarde een instantie van de PrimeFaces-interface SelectableDataModel<T>. De methode [Form].getPersonnes van het model is als volgt gewijzigd:
public DataTableModel getPersonnes() {
return new DataTableModel(personnes);
}
Er wordt dus een nieuwe bean aan het project toegevoegd:
![]() |
Deze bean is de volgende:
package forms;
import java.util.List;
import javax.faces.model.ListDataModel;
import org.primefaces.model.SelectableDataModel;
public class DataTableModel extends ListDataModel<Personne> implements SelectableDataModel<Personne> {
// constructors
public DataTableModel() {
}
public DataTableModel(List<Personne> personnes) {
super(personnes);
}
@Override
public Object getRowKey(Personne personne) {
return personne.getId();
}
@Override
public Personne getRowData(String rowKey) {
// lijst met personen
List<Personne> personnes = (List<Personne>) getWrappedData();
// de sleutel is een geheel getal
int key = Integer.parseInt(rowKey);
// de geselecteerde persoon wordt opgezocht
for (Personne personne : personnes) {
if (personne.getId() == key) {
return personne;
}
}
// er is niets gevonden
return null;
}
}
- regel 7: de klasse is een instantie van de interface SelectableDataModel. Ten minste twee klassen implementeren deze interface: ListDataModel, waarvan de constructor een lijst als parameter accepteert, en ArrayDataModel, waarvan de constructor een array als parameter accepteert. Hier is onze bean een afgeleide van de klasse ListDataModel,
- regels 13-15: de constructor accepteert als parameter de lijst met personen die we beheren. Deze parameter wordt doorgegeven aan de bovenliggende klasse,
- regel 18: de methode getRowKey vervult de rol van het attribuut rowkey dat is verwijderd. Deze methode moet het object retourneren waarmee een persoon uniek kan worden geïdentificeerd, in dit geval de id van de persoon,
- regel 23: de methode getRowData moet het geselecteerde object retourneren op basis van de rowkey. In dit geval dus een persoon op basis van diens id. De aldus verkregen referentie wordt toegewezen aan het doelobject van het selection-attribuut in de tag dataTable, in dit geval het attribuut selection="#{form.personneChoisie}". De parameter van de methode is de rowkey van het door de gebruiker geselecteerde object, in de vorm van een tekenreeks,
- regels 24-35: leveren de referentie op van de persoon waarvan de id is ontvangen. Deze referentie wordt toegewezen aan het model [Form].personneChoisie. De methode [retirerPersonne] blijft dus ongewijzigd:
public void retirerPersonne() {
// de gekozen persoon wordt verwijderd
personnes.remove(personneChoisie);
}
Dit is de techniek die moet worden gebruikt wanneer de koppeling tussen de attributen rowkey en selection geen eenvoudige koppeling is tussen een eigenschap (rowkey**) en een object (selection**).
5.16. Voorbeeld: mv-pf-13: dataTable - 4
Dit project is vergelijkbaar met het vorige, behalve dat de manier waarop de te verwijderen persoon wordt geselecteerd, verandert:

Hierboven zien we dat het object wordt geselecteerd via een contextmenu (rechtsklikken). Er wordt om bevestiging van het verwijderen gevraagd:
![]() |
Het formulier [index.xhtml] verandert als volgt:
...
<ui:composition template="layout.xhtml">
<ui:define name="contenu">
<!-- titel -->
<h2><h:outputText value="#{msg['app.titre2']}"/></h2>
<!-- contextmenu -->
<p:contextMenu for="personnes">
<p:menuitem value="#{msg['form.supprimer']}" onclick="confirmation.show()"/>
</p:contextMenu>
<!-- dialoogvenster -->
<p:confirmDialog widgetVar="confirmation" message="#{msg['form.suppression.confirmation']}"
header="#{msg['form.suppression.message']}" severity="alert" >
<p:commandButton value="#{msg['form.supprimer.oui']}" update=":formulaire:contenu" action="#{form.retirerPersonne}" oncomplete="confirmation.hide()"/>
<p:commandButton value="#{msg['form.supprimer.non']}" onclick="confirmation.hide()" type="button" />
</p:confirmDialog>
<!-- dataTable-->
<p:dataTable id="personnes" value="#{form.personnes}" var="personne" emptyMessage="#{msg['form.noData']}"
selection="#{form.personneChoisie}" selectionMode="single">
...
</p:dataTable>
</ui:define>
</ui:composition>
</html>
- regels 9-11: definiëren een contextmenu voor (attribuut for) het dataTable van regel 21 (attribuut id). Dit contextmenu verschijnt dus bij een klik met de rechtermuisknop op de tabel met personen,
- regel 10: ons menu heeft slechts één optie (tag menuItem). Wanneer op deze optie wordt geklikt, wordt de JavaScript-code van het onclick-attribuut uitgevoerd. De JavaScript-code [confirmation.show()] zorgt ervoor dat het dialoogvenster van regel 14 (attribuut widgetVar) wordt weergegeven. Dit is als volgt:
![]() |
- regel 14: het attribuut message zorgt ervoor dat [3] wordt weergegeven, het attribuut header zorgt ervoor dat [1] wordt weergegeven, het attribuut severity zorgt ervoor dat het pictogram [2] wordt weergegeven,
- regel 16: geeft [4] weer. Bij een klik wordt de persoon verwijderd (attribuut action), waarna het dialoogvenster wordt gesloten (attribuut oncomplete). Het attribuut oncomplete is JavaScript-code die wordt uitgevoerd zodra de actie aan de serverzijde is uitgevoerd,
- regel 17: geeft [5] weer. Bij een klik wordt het dialoogvenster gesloten en wordt de persoon niet verwijderd.
5.17. Voorbeeld: mv-pf-14: dataTable - 5
Dit project laat zien dat het mogelijk is om een reactie van de server te ontvangen na het uitvoeren van een aanroep van AJAX. Hiervoor wordt het attribuut oncomplete van de aanroep AJAX gebruikt:
![]() |
Het formulier [index.xhtml] ziet er als volgt uit:
...
<ui:composition template="layout.xhtml">
<ui:define name="contenu">
...
<!-- dialoogvenster 1 -->
<p:confirmDialog widgetVar="confirmation" ... >
<p:commandButton value="#{msg['form.supprimer.oui']}" update=":formulaire:contenu" action="#{form.retirerPersonne}" oncomplete="handleRequest(xhr, status, args);confirmation.hide()"/>
<p:commandButton ... />
</p:confirmDialog>
<!-- JavaScript -->
<script type="text/javascript">
function handleRequest(xhr, status, args) {
// fout?
if(args.msgErreur) {
alert(args.msgErreur);
}
}
</script>
...
</p:dataTable>
</ui:define>
</ui:composition>
</html>
- regel 7: het attribuut oncomplete roept de JavaScript-functie van de regels 13-18 aan,
- regel 13: de methodesignatuur moet als volgt zijn. args is een woordenboek dat het server-side model kan aanvullen,
- regel 15: er wordt gecontroleerd of het woordenboek args een attribuut heeft met de naam 'msgErreur'. Zo ja, dan wordt het weergegeven (regel 16).
In het model ziet de methode [retirerPersonne] er als volgt uit:
public void retirerPersonne() {
// willekeurig verwijderen
int i = (int) (Math.random() * 2);
if (i == 0) {
// de geselecteerde persoon wordt verwijderd
personnes.remove(personneChoisie);
} else {
// er wordt een foutmelding teruggestuurd
String msgErreur = Messages.getMessage(null, "form.msgErreur", null).getSummary();
RequestContext.getCurrentInstance().addCallbackParam("msgErreur", msgErreur);
}
}
- regel 3: er wordt een willekeurig getal 0 of 1 gegenereerd,
- regels 4-6: als dit 0 is, wordt de door de gebruiker geselecteerde persoon uit de lijst met personen verwijderd,
- regel 9: anders wordt er een geïnternationaliseerde foutmelding opgesteld:
form.msgErreur=La personne n'a pu \u00eatre supprim\u00e9e. Veuillez r\u00e9essayer ult\u00e9rieurement.
form.msgErreur_detail=La personne n'a pu \u00eatre supprim\u00e9e. Veuillez r\u00e9essayer ult\u00e9rieurement.
- regel 10: een ingewikkelde instructie die tot doel heeft om in het eerder genoemde woordenboek 'args' het attribuut met de naam 'msgErreur' toe te voegen, met de waarde msgErreur die in regel 9 is samengesteld. Dit attribuut wordt vervolgens opgehaald door de JavaScript-methode van [index.xhtml]:
<!-- JavaScript -->
<script type="text/javascript">
function handleRequest(xhr, status, args) {
// fout?
if(args.msgErreur) {
alert(args.msgErreur);
}
}
</script>
5.18. Voorbeeld: mv-pf-15: de werkbalk
In dit project bouwen we een werkbalk:
![]() |
De werkbalk is het hierboven omkaderd weergegeven onderdeel. Deze wordt verkregen met de volgende code XHTML, in aansluiting op [index.xhtml]:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="layout.xhtml">
<ui:define name="contenu">
<!-- titel -->
<h2><h:outputText value="#{msg['app.titre2']}"/></h2>
<!-- werkbalk-->
<p:toolbar>
<p:toolbarGroup align="left">
...
</p:toolbarGroup>
<p:toolbarGroup align="right">
...
</p:toolbarGroup>
</p:toolbar>
</ui:define>
</ui:composition>
</html>
- regels 15-22: de werkbalk,
- regels 16-18: definiëren de groep componenten links van de werkbalk,
- regels 19-21: idem voor de componenten rechts.
De componenten links van de werkbalk zijn de volgende:
<p:toolbarGroup align="left">
<h:outputText value="#{msg['form.etudiant']}"/>
<p:spacer width="50px"/>
<p:selectOneMenu value="#{form.personneId}" effect="fade">
<f:selectItems value="#{form.personnes}" var="personne" itemLabel="#{personne.prénom} #{personne.nom}" itemValue="#{personne.id}"/>
</p:selectOneMenu>
<p:separator/>
<p:commandButton id="delete-personne" icon="ui-icon-trash" action="#{form.supprimerPersonne}" update=":formulaire:contenu"/>
<p:tooltip for="delete-personne" value="#{msg['form.delete.personne']}"/>
</p:toolbarGroup>
Ze geven de onderstaande weergave weer:
![]() |
- regel 2: toont [1],
- regel 3: toont een spatie van 30 pixels [2],
- regels 4-6: geven een vervolgkeuzelijst weer met een lijst van personen [3],
- regel 7: toont een scheidingsteken [4],
- regel 8: toont een knop [5] waarmee de in de vervolgkeuzelijst geselecteerde persoon kan worden verwijderd. De knop heeft een pictogram. Deze pictogrammen zijn die van JQuery en UI. De lijst hiermee is te vinden in URL, [http://jqueryui.com/themeroller/] en [6]:
![]() |
- Om de naam van een pictogram te achterhalen, hoeft u er alleen maar met de muis overheen te gaan. Vervolgens wordt deze naam gebruikt in het attribuut `icon` van de component <commandButton>, bijvoorbeeld `icon="ui-icon-trash"`. Merk op dat in het bovenstaande voorbeeld de naam .ui-icon-trash is en dat de eerste punt uit deze naam wordt verwijderd in het attribuut icon,
- regel 9: hiermee wordt een helpballon voor de knop aangemaakt (attribuut `for`). Wanneer de muisaanwijzer op de knop wordt gehouden, wordt het helpbericht [7] weergegeven.
Het sjabloon dat aan deze componenten is gekoppeld, is als volgt:
package forms;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class Form implements Serializable {
// sjabloon
private List<Personne> personnes;
private int personneId;
// fabrikant
public Form() {
// initialisatie van de personenlijst
personnes = new ArrayList<Personne>();
personnes.add(new Personne(1, "dupont", "jacques"));
personnes.add(new Personne(2, "durand", "élise"));
personnes.add(new Personne(3, "martin", "jacqueline"));
}
public void supprimerPersonne() {
// de geselecteerde persoon wordt opgezocht
int i = 0;
for (Personne personne : personnes) {
// huidige persoon = geselecteerde persoon?
if (personne.getId() == personneId) {
// de huidige persoon uit de lijst verwijderen
personnes.remove(i);
// klaar
break;
} else {
// volgende persoon
i++;
}
}
}
// getters en setters
...
}
De componenten rechts van de werkbalk zijn de volgende:
<p:toolbar>
<p:toolbarGroup align="left">
...
</p:toolbarGroup>
<p:toolbarGroup align="right">
<p:menuButton value="#{msg['form.options']}">
<p:menuitem id="menuitem-francais" value="#{msg['form.francais']}" actionListener="#{changeLocale.setFrenchLocale}" update=":formulaire"/>
<p:menuitem id="menuitem-anglais" value="#{msg['form.anglais']}" actionListener="#{changeLocale.setEnglishLocale}" update=":formulaire"/>
</p:menuButton>
</p:toolbarGroup>
</p:toolbar>
Ze geven het onderstaande beeld weer:
![]() |
- regels 6-9: een menuknop. Deze bevat menuopties,
- regel 7: de optie om het formulier in het Frans weer te geven,
- regel 8: de optie om het formulier in het Engels weer te geven.
5.19. Conclusion
We weten nu genoeg om onze voorbeeldtoepassing naar Primefaces over te zetten. We hebben slechts een vijftiental componenten bekeken, terwijl de bibliotheek er meer dan 100 bevat. De lezer wordt uitgenodigd om de component die hij mist rechtstreeks op de Primefaces-website op te zoeken.
5.20. Testen met Eclipse
De Maven-projecten zijn beschikbaar op de website met voorbeelden [1]:
![]() |
Zodra ze in Eclipse zijn geïmporteerd, kunnen ze worden uitgevoerd [2]. Selecteer Tomcat in [3]. Ze worden dan weergegeven in de interne browser van Eclipse [3].
![]() |



















































