p:数据表摘要行计算

时间:2014-09-15 07:23:30

标签: primefaces datatable

我的p:dataTable非常类似于showcase。 不幸的是,展示使用随机生成的p:summaryRow值。

参考展示,假设汽车有价格属性。

如何总结按指定列分组的汽车的价格,以便在摘要行中显示?

5 个答案:

答案 0 :(得分:3)

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

这是一些示例显示总和价格的正确计算,计数......

侦听器获取group属性,该属性是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;
                }
            }
        }
    }
}

答案 1 :(得分: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中的任何字段。

答案 2 :(得分: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>
    ...

嗯,这是完成这项任务的重要方法。我认为你可以改进,但这是我第一次想到你的问题。

希望它有所帮助。

答案 3 :(得分:0)

通过使用Lambda表达式,可以在带有EL 3.0的Java 1.7中使用 在您的JSF中,它将是这样的:

final class SearchViewController: UITableViewController {

  private var searchLoadingController: SearchLoadingController?
  private var searchController: UISearchController?

  convenience init(searchLoadingController: SearchLoadingController, searchController: UISearchController) {
    self.init(nibName: nil, bundle: nil)
    self.searchLoadingController = searchLoadingController
    self.searchController = searchController
  }

  override func viewDidLoad() {
    super.viewDidLoad()
    configureUI()
  }

}

extension SearchViewController: UISearchResultsUpdating {
  func updateSearchResults(for searchController: UISearchController) {
    guard let text = searchController.searchBar.text, !text.isEmpty else { return }
    searchLoadingController?.search(query: text)
  }
}

extension SearchViewController: SearchErrorView {
  func display(_ viewModel: SearchErrorViewModel) { }
}


private extension SearchViewController {
  func configureUI() {
    navigationController?.navigationBar.prefersLargeTitles = true
    navigationItem.searchController = searchController

    tableView.tableFooterView = UIView(frame: .zero)

    searchController?.searchBar.searchBarStyle = .minimal
    searchController?.searchResultsUpdater = self
    searchController?.obscuresBackgroundDuringPresentation = false

    if let searchingView = searchLoadingController?.view {
      tableView.addSubview(searchingView)
      searchingView.translatesAutoresizingMaskIntoConstraints = false
      NSLayoutConstraint.activate([
        searchingView.centerXAnchor.constraint(equalTo: tableView.centerXAnchor),
        searchingView.centerYAnchor.constraint(equalTo: tableView.centerYAnchor)
      ])
    }

  }
}

答案 4 :(得分:0)

一种方法是将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中的侦听器来设置backing 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 ;
}