Supposons que l'on souhaite afficher un formulaire de saisie (ou tout autre composant) de saisie dynamiquement dans une page (affichant d'autres choses) seulement si au moment ou l'utilisateur clique sur un bouton
| Remarque | ||
|---|---|---|
| ||
Schéma ou exemple |
| Sommaire |
|---|
Piste 1 : utiliser le
...
rendered
... celui du form ou d'un panelGrid avec un booléen dans le contrôleur (ici showUserForm)
...
donc update="...panelFormAddUser..." ajax n'a aucun effet puisqu'il n'est pas sur la page.
En revanche si on désactive ajax sur le bouton la page est rechargée complètement :
| Bloc de code |
|---|
<p:commandButton value="Afficher formulaire" actionListener="#{welcomeController.showFormNewUser}" ajax="false"> </p:commandButton> |
... ça marche
Il faut donc un contenant qui s'affiche toujours, qui sera vide par defaut défaut et contiendra le formulaire à l'appel du cliqueclic
Piste 2 : Utiliser un binding
Ceci consiste à mapper un objet qui compose la vue à une propriété du contrôleur.
...
| Bloc de code |
|---|
import javax.faces.component.UIComponent; [...] private UIComponent panelUserForm; [...] public void showFormNewUser() { this.panelUserForm.setRendered(true); } [...] public UIComponent getPanelUserForm() { return panelUserForm; } public void setPanelUserForm(UIComponent panelUserForm) { this.panelUserForm = panelUserForm; } [...] |
... et dans la JSP on mappe :
| Bloc de code |
|---|
<h:panelGrid id="panelFormAddUser" binding="#{welcomeController.panelUserForm}" columns="1" rendered="false">
<h:form id="formAddUser">
[...]
</h:form>
</h:panelGrid>
|
Comme précédemment, update="...panelFormAddUser..." ajax n'a aucun effet puisqu'il n'est pas sur la page.
En revanche si on désactive ajax sur le bouton la page est rechargée complètement :
| Bloc de code |
|---|
<p:commandButton value="Afficher formulaire" actionListener="#{welcomeController.showFormNewUser}" ajax="false">
</p:commandButton> |
... ça marche
Il faut donc un contenant qui s'affiche toujours, qui sera vide par défaut et contiendra le formulaire à l'appel du clic
Piste 3 : Un contenant vide qui sera mis à jour au moment du clic
Pour que seul le panel soit rafraichi avec Ajax e non la page complète nous allons repartir de l'exemple précédent et laisser le panelGrid toujours visible et on va jouer sur la visibilité du formulaire.
| Bloc de code |
|---|
<h:panelGrid id="panelFormAddUser" binding="#{welcomeController.panelUserForm}" columns="1" rendered="true">
<h:form id="formAddUser" rendered="false">
[...]
</h:form>
</h:panelGrid>
|
avec le bouton
| Bloc de code |
|---|
<p:commandButton value="Afficher formulaire" update="@form,panelFormAddUser,growl" action="#{welcomeController.showFormNewUser}" > </p:commandButton> |
Désormais au clic on appellera :
| Bloc de code |
|---|
public void showFormNewUser() {
this.panelUserForm.getChildren().get(0).setRendered(true);
}
|
Là ça marche, au clic le rendered du formulaire est positionné à true et le panel est rafraichi.
Pour améliorer
On va maintenant ajouter un bouton dans le formulaire pour cacher ce dernier.
On a donc l'exemple complet :
| Bloc de code |
|---|
<p:commandButton value="Afficher formulaire" update="@form,panelFormAddUser,growl" action="#{welcomeController.showFormNewUser}" > </p:commandButton> [...] <h:panelGrid id="panelFormAddUser" binding="#{welcomeController.panelUserForm}" columns="1" rendered="true"> <h:form id="formAddUser" rendered="false"> [...] </h:form> <h:form id="formhideAddUser" rendered="false"> <p:commandButton value="Masquer formulaire" update="panelFormAddUser,growl" action="#{welcomeController.hideFormNewUser}" > </p:commandButton> </h:form> </h:panelGrid> |
Désormais aux clics on appellera le cas échéant :
| Bloc de code |
|---|
import javax.faces.component.UIComponent; [...] private UIComponent panelUserForm; public void showFormNewUser() { for (UIComponent component : this.panelUserForm.getChildren()) { component.setRendered(true); } } public void hideFormNewUser() { for (UIComponent component : this.panelUserForm.getChildren()) { component.setRendered(false); } } |
Pour améliorer encore un peu
On intègre le bouton d'affichage du formulaire dans le panel et on switch les rendered
| Bloc de code |
|---|
<h:panelGrid id="panelFormAddUser" binding="#{welcomeController.panelUserForm}" columns="1" rendered="true"> <h:form id="formshowAddUser" rendered="true"> <p:commandButton value="Afficher formulaire" update="@form,panelFormAddUser,growl" action="#{welcomeController.toogleFormNewUser}" > </p:commandButton> </h:form> <h:form id="formAddUser" rendered="false"> [...] </h:form> <h:form id="formhideAddUser" rendered="false"> <p:commandButton value="Masquer formulaire" update="panelFormAddUser,growl" action="#{welcomeController.toogleFormNewUser}" > </p:commandButton> </h:form> </h:panelGrid> |
Désormais aux clics on appellera une seule méthode :
| Bloc de code |
|---|
import javax.faces.component.UIComponent;
[...]
private UIComponent panelUserForm;
public void toogleFormNewUser() {
for (UIComponent component : this.panelUserForm.getChildren()) {
if (component.getAttributes().get("rendered").toString().equals("true"))
component.setRendered(false);
else
component.setRendered(true);
}
}
|
Piste 4 : La solution de facilité... un composant
Primefaces propose par exemple le composant dialog
| Bloc de code |
|---|
<p:commandButton value="Afficher formulaire" onclick="dialogNewUser.show();" type="button"/>
[...]
<p:dialog header="Création d'un utilisateur" widgetVar="dialogNewUser" modal="true">
<h:form id="formAddUser">
[...]
</h:form>
</p:dialog>
|