Question

My product is using JSF with Primefaces 2.2. What I need is to process a sub-datatable inside another datatable. The code is as below.

<h:form>
<p:dataTable id="myInvoiceTable"
    value="#{globalBean.invoices}" var="invoice">

    <p:column>
      <f:facet name="header">
        <h:outputText value="Bill ID" />
      </f:facet>
      <h:outputText value="#{invoice.billId}" />
    </p:column>

    <p:column>
      <f:facet name="header">
        <h:outputText value="Item" />
      </f:facet>
      <h:outputText value="#{invoice.item}" />
    </p:column>

    <p:rowExpansion>

      <h:selectOneMenu id="reasons" value="#{invoiceAction.reason}">
         <f:selectItem itemLabel="Reason 1" itemValue="Reason 1"></f:selectItem>
         <f:selectItem itemLabel="Reason 2" itemValue="Reason 2"></f:selectItem>
      </h:selectOneMenu>

      <p:inputText id="activity_amount" value="#{invoiceAction.activity_amount}"/>

      <p:commandButton value="PROCESS" action="invoice_process" update="actions_table">
      </p:commandButton>

      <p:dataTable id="actions_table" value="#{invoice.actions}" var="invAction">

         <p:column>
            <h:outputText value="#{invAction.reason}" />
         </p:column>

         <p:column>             
            <h:outputText value="#{invAction.activity_amount}" />
         </p:column>

      </p:dataTable>

    </p:rowExpansion>

</p:dataTable>

Here's my bean.

public class Invoice {
    private int billId;
    private String item;
    private List<InvoiceAction> actions;

    // Getter & setter here
}

public class InvoiceAction {
    private String reason;
    private double activity_amount;
    private int billId;

    // Getter & setter here;
}

But when the HTML is generated, it's not processed as desired. Only the select menu in the last row of datatable can receive the data chosen by user, others can't. Because all select menus in all rows are using the same object (#{invoiceAction}), and the bean just gets the value of the last component in the page. I knew the root cause but I don't know how to solve it. How to let they submit in the specified row?

Was it helpful?

Solution

First of all, I think your Invoice and InvoiceAction classes look just like normal Java objects. I feel that they should not be Managed Bean.

Besides, you're right that your #{invoiceAction} is not correctly binded to one of the actions in List<InvoiceAction> actions. Since you are using nested <p:dataTable>, I think you can take advantage of <p:cellEditor>. It would be something like this:

<p:rowExpansion>
   <p:dataTable id="actions_table" value="#{invoice.actions}" var="invAction">

      <p:column>
         <p:cellEditor>  
            <f:facet name="output">  
               <h:outputText value="#{invAction.reason}" />   
            </f:facet>  
            <f:facet name="input">  
               <h:selectOneMenu id="reasons" value="#{invoiceAction.reason}">
                  <f:selectItem itemLabel="Reason 1" itemValue="Reason 1" />
                  <f:selectItem itemLabel="Reason 2" itemValue="Reason 2" />
               </h:selectOneMenu>
            </f:facet>  
         </p:cellEditor>
      </p:column>

      <p:column>
         <p:cellEditor>  
            <f:facet name="output">  
               <h:outputText value="#{invAction.activity_amount}" />   
            </f:facet>  
            <f:facet name="input">  
               <p:inputText id="activity_amount" value="#{invoiceAction.activity_amount}" />
            </f:facet>  
         </p:cellEditor>
      </p:column>

   </p:dataTable>

   <p:commandButton value="PROCESS" action="invoice_process" update="actions_table" />
</p:rowExpansion>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top