How to ajax update an item in the footer of a PrimeFaces dataTable?

10,535

You can't really update the values of the table from within the table. However, you can use p:remoteCommand to achieve this. Also, I would probably use the cellEdit event on the whole table (instead of a single p:ajax on your pe:inputNumber). The overall result would be:

<p:remoteCommand name="refreshFooter" update=":formName:outputTotal"/>
...
<p:dataTable id="myTable" value="#{myBean.someList}" var="currentItem">

    <p:column headerText="Header1">
        <h:outputText value="#{currentItem.name}" />
    </p:column>

    <p:column headerText="Header2">
        <pe:inputNumber value="#{currentItem.inputVal}">
            <p:ajax event="change" listener="#{myBean.changeListener}" process="@this"
                oncomplete="refreshFooter();" update="outputVal"/>
        </pe:inputNumber>
    </p:column>

    <p:column headerText="Header3">
        <h:outputText id="outputVal" value="#{currentItem.outputVal}" />
    </p:column>

    <f:facet name="footer">
        Total:
        <h:outputText id="outputTotal" value="#{myBean.total}" />
    </f:facet>

</p:dataTable>

Please note that you might need to add partialSubmit="true" to the p:ajax, this way you only submit the component's data. If you like the cellEdit event idea, you need to make the dataTable editable, and add the following in your p:dataTable, and get rid of the p:ajax inside your pe:inputNumber

<p:ajax event="cellEdit" partialSubmit="true" listener="#{myBean.onCellEdit}" 
    process="@this" oncomplete="refreshFooter();"/>

Good luck!

Share:
10,535
cobaltduck
Author by

cobaltduck

What’s going on? I’ve observed with interest, but have not participated in, the many meta-discussions surrounding a handful of issues lately. These include the removal of IPS from HNQ, the changing of question vote rep levels, the retro-active switch of the CC version, and most especially, the case of Monica Cellio. I found it all very upsetting, but for too long I chose to merely observe. I did not change my avatar, did not change my user name, did not link to nor donate to the legal defense fund, did not answer or comment on the metas, and more or less continued as normal. I am now ashamed of my lack of action these last few months, and it is time to change. With the recent announcement of the agreement with Monica, and the phrasing of this announcement that clearly blames the victim, I must draw back from activities which might indicate I have even the slightest support for Stack Overflow. I sincerely believe SO has committed criminal libel, violation of content license, and possibly other illegal acts. Further, the leadership has acted in bad faith, and ignored the wishes of its user base. Therefore, for the foreseeable future, my intentions are as follows. I will: if while searching for the answer to an issue or obscure error, and the result includes links to Stack Exchange sites, I will read these. Further, if the question and one or more answer prove useful, I will up-vote as a thank-you to the posters; check once in a while if I have received any new answers or comments to my old contributions, and provide a response as and when necessary. I will not: ask or answer any questions, or comment on any questions or answers; casually browse through questions and answers; perform any reviews or related tasks, i.e. cast close votes; display "flair" on my own website continue to have the Stack Exchange App installed on any mobile devices. My anticipated timeline for this hiatus is the remainder of 2019 and all of 2020. I may be persuaded to alter the timeline if I see definitive indications of change and contrition on the part of Stack Overflow and its leadership. The CobaltDuck flocks with those who think this is wrong, and is flying south for a while. Best Wishes to all my friends on the network.

Updated on June 27, 2022

Comments

  • cobaltduck
    cobaltduck almost 2 years

    This is a visual of the table I have:

    +---------+------------+-------------------+
    | Header1 |  Header2   | Header3           |
    +---------+------------+-------------------+
    | Row A   |  Input A   | Calc'ed output A  |
    | Row B   |  Input B   | Calc'ed output B  |
    | etc..   |  etc..     |  etc..            |
    +---------+------------+-------------------+
    |    Total:          Total calc'ed output  |
    +------------------------------------------+
    

    And the stripped-down code:

    <p:dataTable id="myTable" value="#{myBean.someList}"
        var="currentItem">
    
        <p:column headerText="Header1">
            <h:outputText value="#{currentItem.name}" />
        </p:column>
    
        <p:column headerText="Header2">
            <pe:inputNumber value="#{currentItem.inputVal}">
                <p:ajax event="change" listener="#{myBean.changeListener}"
                    update="outputVal outputTotal" />
            </pe:inputNumber>
        </p:column>
    
        <p:column headerText="Header3">
            <h:outputText id="outputVal" value="#{currentItem.outputVal}" />
        </p:column>
    
        <f:facet name="footer">
            Total:
            <h:outputText id="outputTotal" value="#{myBean.total}" />
        </f:facet>
    
    </p:dataTable>
    

    The myBean.someList is an ArrayList<SomeOtherBean> with one String and two Integers, with just getters and setters. The myBean.changeListener calculates the second Integer from the first for the given row, and also the total for all rows.

    So, when I type in one of the inputs then focus out, the listener is called and the calculation done, but on screen, the value in the third column changes, but the total stubbornly remains zero. I'm fairly sure this has something to do with PrimeFaces appending the row index to the generated id's of each input and output, but I can't figure out how to get to the output in the footer (whose generated id is mainForm:myTable:0:outputTotal).

    Now, I could just update the parent table. However whenever the input to receive focus is part of the update target, the focus is lost, and I am under extremely strict accessibility rules that this table must be keyboard friendly (type a number, tab, type a number, tab, etc...)

    I have tried:

    • update=":outputTotal" (gave exception Cannot find component with identifier...)
    • update="myTable:0:outputTota (same exception)
    • update="myTable:outputTotal" (no update, total stays zero)
    • wrap the text in a panelGroup and update that (no update)

    (PrimeFaces 3.5.0 with MyFaces unknown version)