jsfparameter-passingfaceletsmanaged-beanuiinclude

How to pass bean action/listener method via <ui:param> of <ui:include>


I'm using <ui:include> to load a data table (I'm using Primefaces). I want use <ui:param> in the listener into the tag <p:ajax>. I tested the code that is down, but not trigger the event onRowEdit or onRowCancel. This is my page:

...
<ui:include src="../Componentes/tablaEditable.xhtml">
     <ui:param name="columnas" value="#{tabla2FuentesHL7.dataTableColumns}" />
     <ui:param name="bean" value="#{tabla2FuentesHL7.listTabla2FuenteDTO}" />
     <ui:param name="aceptarEdicion" value="#{tabla2FuentesHL7.onRowEdit}" />
     <ui:param name="cancelarEdicion" value="#{tabla2FuentesHL7.onRowCancel}" />
</ui:include>
...

My data table:

<ui:composition 
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">

<h:form >
    <p:dataTable value="#{bean}"  scrollable="true"  scrollHeight="100" var="dato" editable="true">
        <p:ajax event="rowEdit" listener="#{aceptarEdicion}"  />
        <p:ajax event="rowEditCancel" listener="#{cancelarEdicion}"  />
        <c:forEach items="#{columnas}" var="column" varStatus="loop">
            <p:column headerText="#{column.header}" sortBy="#{dato[column.property]}">
                <p:cellEditor>
                    <f:facet name="output">
                        <h:outputText value="#{dato[column.property]}" />
                    </f:facet>
                    <f:facet name="input">
                        <p:inputText value="#{dato[column.property]}" style="width:100%"  />
                    </f:facet>
                </p:cellEditor>     
            </p:column>
        </c:forEach> 
        <p:column style="width:32px">
            <p:rowEditor />
        </p:column>
    </p:dataTable>
</h:form>

My bean:

@ManagedBean(name = "tabla2FuentesHL7")
@ViewScoped
enter code herepublic class Tabla2FuentesHL7 {

private static final long serialVersionUID = 1L;
private List<DataTableColumn> dataTableColumns = new ArrayList<DataTableColumn>();
private List<Tabla2FuenteDTO> listTabla2FuenteDTO = new ArrayList<Tabla2FuenteDTO>();

@PostConstruct
public void init() {

    listTabla2FuenteDTO = Test.getFuenteTabla2();
    dataTableColumns = CargarTablas.getTabla2FuenteHL7();

}

public List<Tabla2FuenteDTO> getListTabla2FuenteDTO() {
    return listTabla2FuenteDTO;
}

public List<DataTableColumn> getDataTableColumns() {
    return dataTableColumns;
}

public void onRowEdit(RowEditEvent event) {
    FacesMessage msg = new FacesMessage("Elemento modificado");
    FacesContext.getCurrentInstance().addMessage(null, msg);
}

public void onRowCancel(RowEditEvent event) {
    FacesMessage msg = new FacesMessage("Modificación cancelada");
    FacesContext.getCurrentInstance().addMessage(null, msg);
}

public void onCellEdit(CellEditEvent event) {
    Object oldValue = event.getOldValue();
    Object newValue = event.getNewValue();

    if (newValue != null && !newValue.equals(oldValue)) {
        FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Cell Changed", "Old: " + oldValue + ", New:" + newValue);
        FacesContext.getCurrentInstance().addMessage(null, msg);
    }
}

}

This is the error:

javax.el.PropertyNotFoundException: /Componentes/tablaEditable.xhtml @12,76 listener="#{cancelarEdicion}": /Modulos/hl7.xhtml @31,104 value="#{tabla2FuentesHL7.onRowCancel}": The class 'com.queres.xedoc.consola.componentes.Tabla2FuentesHL7' does not have the property 'onRowCancel'.

If I change this:

<p:ajax event="rowEdit" listener="#{aceptarEdicion}"  />
        <p:ajax event="rowEditCancel" listener="#{cancelarEdicion}"  />

for this:

        <p:ajax event="rowEdit" listener="#{tabla2FuentesHL7.onRowEdit}"  />
        <p:ajax event="rowEditCancel" listener="#{tabla2FuentesHL7.onRowCancel}"  />

my code works fine, but I need a dynamic data table. Is there any way to pass a parameter to the listener? Thanks!


Solution

  • The <ui:param> can only pass value expressions, not method expressions.

    Better make use of the ability of EL to parameterize method names via brace [] notation. Then you can just declare the method names as plain vanilla String.

    <ui:include src="../Componentes/tablaEditable.xhtml">
         ...
         <ui:param name="beanEdicion" value="#{tabla2FuentesHL7}" />
         <ui:param name="aceptarEdicion" value="onRowEdit" />
         <ui:param name="cancelarEdicion" value="onRowCancel" />
    </ui:include>
    
    <p:ajax event="rowEdit" listener="#{beanEdicion[aceptarEdicion]()}"  />
    <p:ajax event="rowEditCancel" listener="#{beanEdicion[cancelarEdicion]()}"  />
    

    Update as per the comments, it appears to still not work in PrimeFaces 5.1 even though the related issue says that it's already fixed in 3.5. You'd basically need to reopen the issue.

    In the meanwhile, you can workaround this with help of <o:methodParam> tag of JSF utility library OmniFaces. This basically converts a value expression to a method expression:

    <ui:include src="../Componentes/tablaEditable.xhtml">
             ...
         <ui:param name="aceptarEdicion" value="#{tabla2FuentesHL7.onRowEdit}" />
         <ui:param name="cancelarEdicion" value="#{tabla2FuentesHL7.onRowCancel}" />
    </ui:include>
    
    <o:methodParam name="aceptarEdicionParam" value="#{aceptarEdicion}" />
    <o:methodParam name="cancelarEdicionParam" value="#{cancelarEdicion}" />
    ...
    <p:ajax event="rowEdit" listener="#{aceptarEdicionParam}"  />
    <p:ajax event="rowEditCancel" listener="#{cancelarEdicionParam}"  />