feat(client): Implementation de Composite Components JSF avec method-signature

SOLUTION TROUVEE via recherches:
- Utilisation de Composite Components JSF au lieu de ui:include/ui:decorate
- Declaration avec composite:interface et composite:attribute method-signature
- Permet de passer actionListener correctement via cc.attrs.actionListener

COMPOSANTS CREES dans resources/components:
- action-button-edit.xhtml : Composite Component pour bouton Modifier
- action-button-toggle.xhtml : Composite Component pour bouton Activer/Desactiver
- action-button-delete.xhtml : Composite Component pour bouton Supprimer

USAGE dans liste.xhtml:
xmlns:uf http://xmlns.jcp.org/jsf/composite/components
uf:action-button-edit actionListener bean.method(item) update form dialogWidget dlg

Cette approche est la bonne pratique JSF officielle pour passer des expressions de methode.
Resout definitivement: Identity action does not reference a method expression
This commit is contained in:
dahoud
2025-11-29 22:28:03 +00:00
parent 538d9a6f4e
commit 7e9b1c0bdb
4 changed files with 100 additions and 26 deletions

View File

@@ -3,7 +3,8 @@
xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core" xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"> xmlns:p="http://primefaces.org/ui"
xmlns:uf="http://xmlns.jcp.org/jsf/composite/components">
<ui:composition template="/templates/main-template.xhtml"> <ui:composition template="/templates/main-template.xhtml">
<ui:define name="title">Gestion des Organisations</ui:define> <ui:define name="title">Gestion des Organisations</ui:define>
@@ -174,32 +175,23 @@
<ui:param name="styleClass" value="mr-2"/> <ui:param name="styleClass" value="mr-2"/>
</ui:include> </ui:include>
<p:commandButton value="Modifier" <!-- DRY/WOU: Composite Component action-button-edit -->
icon="pi pi-pencil" <uf:action-button-edit actionListener="#{organisationsBean.setOrganisationSelectionnee(org)}"
actionListener="#{organisationsBean.setOrganisationSelectionnee(org)}" update=":formModifier"
oncomplete="PF('dlgModifier').show();" dialogWidget="dlgModifier"
update=":formModifier" styleClass="mr-2"/>
styleClass="ui-button-rounded ui-button-text ui-button-warning mr-2"/>
<p:commandButton value="#{org.statut == organisationsBean.statutActive ? 'Désactiver' : 'Activer'}"
icon="#{org.statut == organisationsBean.statutActive ? 'pi pi-ban' : 'pi pi-check'}"
actionListener="#{organisationsBean.basculerStatutOrganisation(org)}"
update=":formOrganisations:dtOrganisations :formOrganisations:messages"
styleClass="ui-button-rounded ui-button-text #{org.statut == organisationsBean.statutActive ? 'ui-button-secondary' : 'ui-button-success'} mr-2">
<p:confirm header="Confirmation"
message="Êtes-vous sûr de vouloir changer le statut de cette organisation ?"
icon="pi pi-exclamation-triangle"/>
</p:commandButton>
<p:commandButton value="Supprimer" <!-- DRY/WOU: Composite Component action-button-toggle -->
icon="pi pi-trash" <uf:action-button-toggle actionListener="#{organisationsBean.basculerStatutOrganisation(org)}"
actionListener="#{organisationsBean.supprimerOrganisation(org)}" update=":formOrganisations:dtOrganisations :formOrganisations:messages"
update=":formOrganisations:dtOrganisations :formOrganisations:messages" isActive="#{org.statut == organisationsBean.statutActive}"
styleClass="ui-button-rounded ui-button-text ui-button-danger"> confirmMessage="Êtes-vous sûr de vouloir changer le statut de cette organisation ?"
<p:confirm header="Confirmation" styleClass="mr-2"/>
message="Êtes-vous sûr de vouloir supprimer cette organisation ? Cette action est irréversible."
icon="pi pi-exclamation-triangle"/> <!-- DRY/WOU: Composite Component action-button-delete -->
</p:commandButton> <uf:action-button-delete actionListener="#{organisationsBean.supprimerOrganisation(org)}"
update=":formOrganisations:dtOrganisations :formOrganisations:messages"
confirmMessage="Êtes-vous sûr de vouloir supprimer cette organisation ? Cette action est irréversible."/>
</p:column> </p:column>
</p:dataTable> </p:dataTable>
</ui:define> </ui:define>

View File

@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:composite="http://xmlns.jcp.org/jsf/composite"
xmlns:p="http://primefaces.org/ui">
<composite:interface>
<composite:attribute name="actionListener"
method-signature="void actionListener(jakarta.faces.event.ActionEvent)"
required="true"/>
<composite:attribute name="update" type="java.lang.String" required="false"/>
<composite:attribute name="confirmMessage" type="java.lang.String" required="false" default="Êtes-vous sûr de vouloir supprimer ?"/>
<composite:attribute name="styleClass" type="java.lang.String" required="false" default=""/>
</composite:interface>
<composite:implementation>
<p:commandButton value="Supprimer"
icon="pi pi-trash"
actionListener="#{cc.attrs.actionListener}"
update="#{cc.attrs.update}"
styleClass="ui-button-rounded ui-button-text ui-button-danger #{cc.attrs.styleClass}">
<p:confirm header="Confirmation"
message="#{cc.attrs.confirmMessage}"
icon="pi pi-exclamation-triangle"/>
</p:commandButton>
</composite:implementation>
</html>

View File

@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:composite="http://xmlns.jcp.org/jsf/composite"
xmlns:p="http://primefaces.org/ui">
<composite:interface>
<composite:attribute name="actionListener"
method-signature="void actionListener(jakarta.faces.event.ActionEvent)"
required="true"/>
<composite:attribute name="update" type="java.lang.String" required="false"/>
<composite:attribute name="dialogWidget" type="java.lang.String" required="true"/>
<composite:attribute name="styleClass" type="java.lang.String" required="false" default="mr-2"/>
</composite:interface>
<composite:implementation>
<p:commandButton value="Modifier"
icon="pi pi-pencil"
actionListener="#{cc.attrs.actionListener}"
oncomplete="PF('#{cc.attrs.dialogWidget}').show();"
update="#{cc.attrs.update}"
styleClass="ui-button-rounded ui-button-text ui-button-warning #{cc.attrs.styleClass}"/>
</composite:implementation>
</html>

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:composite="http://xmlns.jcp.org/jsf/composite"
xmlns:p="http://primefaces.org/ui">
<composite:interface>
<composite:attribute name="actionListener"
method-signature="void actionListener(jakarta.faces.event.ActionEvent)"
required="true"/>
<composite:attribute name="update" type="java.lang.String" required="false"/>
<composite:attribute name="isActive" type="java.lang.Boolean" required="true"/>
<composite:attribute name="confirmMessage" type="java.lang.String" required="false" default="Êtes-vous sûr ?"/>
<composite:attribute name="styleClass" type="java.lang.String" required="false" default="mr-2"/>
</composite:interface>
<composite:implementation>
<p:commandButton value="#{cc.attrs.isActive ? 'Désactiver' : 'Activer'}"
icon="#{cc.attrs.isActive ? 'pi pi-ban' : 'pi pi-check'}"
actionListener="#{cc.attrs.actionListener}"
update="#{cc.attrs.update}"
styleClass="ui-button-rounded ui-button-text #{cc.attrs.isActive ? 'ui-button-secondary' : 'ui-button-success'} #{cc.attrs.styleClass}">
<p:confirm header="Confirmation"
message="#{cc.attrs.confirmMessage}"
icon="pi pi-exclamation-triangle"/>
</p:commandButton>
</composite:implementation>
</html>