Datatable摘要行计算

4
我有一个与演示非常相似的 p:dataTable。 不幸的是,演示使用随机生成的值来展示p:summaryRow
参考演示,想象一下汽车拥有价格属性。
我该如何按指定列对汽车价格进行汇总并在汇总行中显示?
5个回答

3

我和你有同样的问题,并从primefaces博客中找到了正确的用法SummaryRow from primefaces forum

这是一些示例,展示了正确计算总价、数量等的方法...

监听器获取组属性,即sortBy值,您可以使用它来计算总数或任何其他操作。

<p:summaryRow listener="#{backingBean.calculateTotal}"> 
                        <p:column colspan="3" style="text-align:right"> 
                            Total: 
                        </p:column> 

                        <p:column> 
                            #{backingBean.total}
                        </p:column> 
                    </p:summaryRow>

/* listener method in your bean */
public void calculateTotal(Object o) {
    this.total = 0.0d;
    String name = "";
    if(o != null) {
        if(o instanceof String) {
            name = (String) o;
            for(MyRowObject p : (List<MyRowObject>) dataTableModel.getWrappedData()) { // The loop should find the sortBy value rows in all dataTable data.
                switch(sortColumnCase) { // sortColumnCase was set in the onSort event
                    case 0:
                        if(p.getcolumn0data().getName().equals(name)) {
                            this.total += p.getcolumn0data().getValue();
                        }
                        break;
                    case 1:
                        if(p.getcolumn1data().getName().equals(name)) {
                            this.total += p.getcolumn1data().getValue();
                        }
                        break;
                }
            }
        }
    }
}

2

这是我的解决方案:

<p:dataTable var="elem" value="#{unitSubStatusChart.resultList}" tableStyleClass="app-table-auto">
    <et:defaultPaginator />

    <p:column headerText="#{bundle['class']}" sortBy="#{elem.dtype}">
        <e:outputIconText icon="#{icons[elem.dtype]}" value="#{bundle[elem.dtype]}" />
    </p:column>
    <p:column headerText="#{bundle['status']}" sortBy="#{elem.status}">
        <h:outputText value="#{bundle[elem.status]}" />
    </p:column>
    <p:column headerText="#{bundle['subStatus']}" sortBy="#{elem.subStatus}">
        <h:outputText value="#{bundle[elem.subStatus]}" />
    </p:column>
    <p:column headerText="#{bundle['count']}">
        <h:outputText value="#{elem.count}" />
    </p:column>

    <p:summaryRow listener="#{unitSubStatusChart.onSummaryRow}">
        <p:column colspan="3" style="text-align:right">
            <h:outputText value="#{bundle.total}:" />
        </p:column>
        <p:column>
            <!-- !!! NOTE THIS VALUE EXPRESSION !!! -->
            <h:outputText value="#{component.parent.attributes.total}" />
        </p:column>
    </p:summaryRow>
</p:dataTable>

这是监听器:

public void onSummaryRow(Object filter)
{
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ELContext elContext = facesContext.getELContext();
    ELResolver elResolver = elContext.getELResolver();

    DataTable table = (DataTable) UIComponent.getCurrentComponent(facesContext);

    UIColumn sortColumn = table.getSortColumn();
    ValueExpression expression = sortColumn.getValueExpression("sortBy");
    ValueReference reference = ValueExpressionAnalyzer.getReference(expression);
    String property = (String) reference.getProperty();

    int total = 0;
    List<?> rowList = (List<?>) table.getValue();
    for(Object row : rowList)
    {
        Object value = elResolver.getValue(elContext, row, property);
        if(filter.equals(value))
        {
            // THIS IS THE ONLY POINT TO CUSTOMIZE
            total += ((UnitResult) row).getCount();
        }
    }

    List<UIComponent> children = table.getSummaryRow().getChildren();
    UIComponent column = children.get(children.size() - 1);
    column.getAttributes().put("total", total);
}

这个监听器没有外部引用:它不依赖于以前的onSort事件/监听器,也不需要bean中的任何字段。

1
我将提供一种可能的方法来实现这个,可能不是最完美的,但我相信它会有所帮助。
以下是步骤:
1 - 声明一个类属性来累计总组值:
...
@Named(value = "myBean")
@YourScope

public class InscricaoBean implements Serializable {
...

//in this example i will use a int type

private int acumulatorAux = 0;
...

2 - 创建一个函数以返回每个组的总值:

...
public int getAcumulatedValue() {
        int aux = acumulatorAux ;
        acumulatorAux = 0;
        return aux;
    }
...

3 - 创建一个方法来按组累积值:

...
public void acumulateValue(int value)
    {
        acumulatorAux += value;
    }
...

4 - 在JSF页面上,您需要为每一行调用acumulateValue方法,类似于:

...
<p:dataTable value="#{myBean.getList()}" var="testVar">
       <p:column headerText="Header" sortBy="#{testVar.name}">
            #{inscricaoBean.acumulateValue(testVar.value)}
            <h:outputText value="#{testVar.name}" />
       </p:column>
 ...

5 - 接下来,您可以拥有一个像这样的summaryRow:

    ...
    <p:summaryRow>
        <p:column colspan="1" style="text-align:right">
              <h:outputText value="Total:" />
        </p:column>
        <p:column>
              <h:outputText value="#{inscricaoBean.getAcumulatedValue()}" />
        </p:column>
    </p:summaryRow>
    ...

好的,这是一种粗糙的完成任务的方式。我认为你可以改进,但这是我看到你的问题时想到的第一件事。

希望能有所帮助。


在summaryRow中使用多个列,这是唯一对我有效的方法。 - Rasshu

0
一种方法是将datatable的sortBy =“#{car.brand}”值传递到p:summaryRow中,然后在支持方法中使用流来计算价格小计。
<h:form>
    <p:dataTable var="car" value="#{dtSummaryRowView.cars}" sortBy="#{car.brand}">
        <p:column headerText="Id" sortBy="#{car.id}">
            <h:outputText value="#{car.id}" />
        </p:column>
        <p:column headerText="Year" sortBy="#{car.year}">
            <h:outputText value="#{car.year}" />
        </p:column>
        <p:column headerText="Brand" sortBy="#{car.brand}">
            <h:outputText value="#{car.brand}" />
        </p:column>
        <p:column headerText="Color" sortBy="#{car.color}">
            <h:outputText value="#{car.color}" />
        </p:column>
        <p:summaryRow>
            <p:column colspan="3" style="text-align:right">
                <h:outputText value="Total:" />
            </p:column>
            <p:column>
                <h:outputText value="#{dtSummaryRowView.brandSubtotal(car.brand)}">
                    <f:convertNumber type="currency" currencySymbol="$" />
                </h:outputText>
            </p:column>
        </p:summaryRow>
    </p:dataTable>
</h:form>

.

public double brandSubtotal(String brand) {
    return cars.stream().filter(c -> c.getBrand().equals(brand)).mapToDouble(c -> c.getPrice()).sum();
}

另一种方法是使用 p:summaryRow 中的监听器来设置一个后备 bean 属性,然后使用 getter 来显示该属性。
    <p:summaryRow listener="#{dtSummaryRowView.computeSubtotal(car.brand)}">
        <p:column colspan="3" style="text-align:right">
            <h:outputText value="Total:" />
        </p:column>
        <p:column>
            <h:outputText value="#{dtSummaryRowView.subTotal}">
                <f:convertNumber type="currency" currencySymbol="$" />
            </h:outputText>
        </p:column>
    </p:summaryRow>

.

public void computeSubtotal(String brand) {
    subTotal = cars.stream().filter(c -> c.getBrand().equals(brand)).mapToDouble(c -> c.getPrice()).sum();
}

public double getSubTotal () {
    return subTotal ;
}

0

通过使用Lambda表达式,它可以在Java 1.7和EL 3.0中工作。 在您的JSF中,它应该像这样:

 <p:summaryRow>
  <p:column colspan="3" style="text-align:right">
   <h:outputText value="Total:" />
  </p:column>
  <p:column>
    <h:outputText value="#{car.stream().map(item->item.price).sum()}">
     <f:convertNumber type="currency" currencySymbol="$" />
    </h:outputText>
  </p:column>
 </p:summaryRow>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接