【问题标题】:How to ajax update an item in the footer of a PrimeFaces dataTable?如何 ajax 更新 PrimeFaces 数据表页脚中的项目?
【发布时间】:2022-03-04 23:18:41
【问题描述】:

这是我所拥有的表格的视觉效果:

+---------+------------+------------------+ |页眉1 |页眉2 |页眉3 | +---------+------------+------------------+ | A 行 |输入 A |计算输出 A | | B 行 |输入 B |计算输出 B | |等等。 |等等。 |等等。 | +---------+------------+------------------+ |总计:总计算输出 | +--------------------------------------------+

以及精简后的代码:

<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>

myBean.someList 是一个 ArrayList&lt;SomeOtherBean&gt;,有一个 String 和两个 Integer,只有 getter 和 setter。 myBean.changeListener 计算给定行的第一个整数的第二个整数,以及所有行的总数。

因此,当我输入其中一个输入然后聚焦时,将调用侦听器并完成计算,但在屏幕上,第三列中的值发生了变化,但总和顽固地保持为零。我相当确定这与 PrimeFaces 将行索引附加到每个输入和输出的生成 id 有关,但我不知道如何到达页脚中的输出(其生成的 id 是mainForm:myTable:0:outputTotal )。

现在,我可以更新父表了。但是,只要接收焦点的输入是更新目标的一部分,焦点就会丢失,并且我处于极其严格的可访问性规则下,该表必须是键盘友好的(输入数字、制表符、输入数字、制表符等...)

我试过了:

  • update=":outputTotal"(给出异常找不到具有标识符的组件...)
  • update="myTable:0:outputTota(同样的例外)
  • update="myTable:outputTotal"(无更新,总数为零)
  • 将文本包装在 panelGroup 中并更新(不更新)

(PrimeFaces 3.5.0 和 MyFaces 未知版本)

【问题讨论】:

    标签: ajax jsf primefaces accessibility


    【解决方案1】:

    您不能真正从表中更新表的值。但是,您可以使用p:remoteCommand 来实现此目的。此外,我可能会在整个表格上使用 cellEdit 事件(而不是在您的 pe:inputNumber 上使用单个 p:ajax)。总体结果是:

    <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>
    

    请注意,您可能需要partialSubmit="true" 添加到p:ajax,这样您只需提交组件的数据。如果您喜欢 cellEdit 事件的想法,您需要使 dataTable 可编辑,并在您的p:dataTable 中添加以下内容,并在您的pe:inputNumber 中删除p:ajax

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

    祝你好运!

    【讨论】:

      【解决方案2】:

      更新 PrimeFaces

      这个问题最终在 PrimeFaces 11 或 PrimeFaces Elite 8.0.8 / 10.0.1 中得到修复。使用 PrimeFaces 11+,您可以在数据表上使用 partialUpdate="false"。此修复的缺点是它还会更新标题(和过滤器),因此它可能会在您键入时为您更新过滤器输入。您可以在过滤器事件上设置delay 来改善这一点,但效果不会消失,只是不太明显。

      见:

      PrimeFaces.ab 而不是 p:remoteCommand

      如果您不想创建 p:remoteCommands 来更新数据表 filter 事件上的组件(好吧,我不想),您可以使用:

      <p:ajax event="filter"
              oncomplete="PrimeFaces.ab({source:'#{component.clientId}',process:'@none',update:'componentToUpdate'})"/>
      

      没错,这看起来有点乱,但您可以创建一个自定义 EL 函数来将其简化为:

      <p:ajax event="filter"
              oncomplete="#{my:ajaxUpdate('componentToUpdate')}"/>
      

      【讨论】:

        猜你喜欢
        • 2015-01-14
        • 1970-01-01
        • 2013-02-27
        • 2013-07-30
        • 2015-07-19
        • 2013-09-25
        • 2013-09-05
        • 2017-08-17
        • 2012-01-14
        相关资源
        最近更新 更多