简体   繁体   English

PrimeFaces Datatable:如何接收选定的行值?

[英]PrimeFaces Datatable: How to receive selected rows values?

I use Prime Faces 6.2 to make a data table with checked column:我使用 Prime Faces 6.2 制作带有选中列的数据表:

<p:dataTable id="#{prefix}List"
                 value="#{tickets}"
                 lazy="true"
                 paginator="true"
                 paginatorTemplate="{FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
                 currentPageReportTemplate="{startRecord}-{endRecord} из {totalRecords}"
                 rows="20"
                 rowKey="#{ticket.id}"
                 var="ticket"
                 emptyMessage="Записи в данной категории отсутствуют">

    <p:ajax event="toggleSelect" listener="#{ticketForm.onAllSelect}" process="@this" partialSubmit="true" />
    <p:ajax event="rowSelectCheckbox" listener="#{ticketForm.onSelect}" update=":protocolForm" />
    <p:ajax event="rowUnselectCheckbox" listener="#{ticketForm.onUnselect}" update=":protocolForm" />
    <p:ajax event="rowSelect" listener="#{ticketForm.onSelect}" update=":protocolForm" />
    <p:ajax event="rowUnselect" listener="#{ticketForm.onUnselect}" update=":protocolForm" />
     
    <p:column selectionMode="multiple" style="width:40px; text-align:center" />
    

More specifically, when a header checkbox is selected I want to receive all selected rows data on server-side and use IDs of each row.更具体地,选择标题复选框时,我希望在服务器端接收所有选定的行数据并使用每行的ID。 Also, there's logic that helps to resolve a goal of hidding/rendering a page button when at least one checkbox is selected.此外,当至少一个复选框被选中时,还有一些逻辑有助于解决隐藏/呈现页面按钮的目标。

For this purpose I need manualy intercept a row/checkbox selection event and record IDs from it when a button pushed, so I can't use selection attribute of dataTable using such logic.为此,我需要在按下按钮时手动拦截行/复选框选择事件并从中记录 ID,因此我不能使用这种逻辑使用 dataTable 的selection属性。

On server-side I have several event-listeners:在服务器端,我有几个事件监听器:

private Set<AbstractMTSBUExportTicket> abstractMTSBUExportTickets = new HashSet<>();

public Set<AbstractMTSBUExportTicket> getAbstractMTSBUExportTickets() {
    return abstractMTSBUExportTickets;
}

public void onSelect(SelectEvent event) {
    abstractMTSBUExportTickets.add((AbstractMTSBUExportTicket) event.getObject());
}

public void onUnselect(UnselectEvent event) {
    abstractMTSBUExportTickets.remove(event.getObject());
}

public void onAllSelect(ToggleSelectEvent event) {
    // do smth
}

Unfortunately, ToggleSelectEvent has only information about data-table itself within.不幸的是,ToggleSelectEvent 仅包含有关数据表本身的信息。

None information about rows I couldn't find.没有关于我找不到的行的信息。 Also I tried to add process="@this" partialSubmit="true" attributes but seems like they do different actions.我还尝试添加process="@this" partialSubmit="true"属性,但似乎它们执行不同的操作。

So, could you give me an example of how it's possible to retrieve such data from an event object?那么,您能否举个例子说明如何从事件对象中检索此类数据? Should I use another way to solve it?我应该使用其他方法来解决它吗? Thanks for your answers in advance.提前感谢您的回答。

You're use lazy dataTable and this doesn't stay the selection on page change.您正在使用惰性数据表,这不会保留页面更改时的选择。

  1. You need set the selection param with a type of your collection您需要使用您的集合类型设置selection参数

  2. Implement getRowKey inside your LazyDataModel and remove rowKey="#{ticket.id}"LazyDataModel getRowKey删除rowKey="#{ticket.id}"

  3. Selection with checkbox doesn't need selectionMode="multiple" .带复选框的选择不需要selectionMode="multiple"

    • This param is only for multiple selection when click on the table row with CTRL is pressed此参数仅用于在按住 CTRL 键单击表格行时进行多选
  4. My sugestion is control your selected data manualy我的建议是手动控制您选择的数据

XHTML file: XHTML 文件:

<p:dataTable id="#{prefix}List"
                 value="#{tickets}"
                 lazy="true"
                 paginator="true"
                 var="ticket"
                 selection="#{ticketForm.selectedTickets}"
                 emptyMessage="Записи в данной категории отсутствуют">

    <p:ajax event="toggleSelect" 
            listener="#{ticketForm.onAllSelect}" partialSubmit="true"/>
    <p:ajax event="rowSelectCheckbox" 
            listener="#{ticketForm.onSelect}" update=":protocolForm"/>
    <p:ajax event="rowUnselectCheckbox" 
            listener="#{ticketForm.onUnselect}" update=":protocolForm"/>
    <p:ajax event="rowSelect" 
            listener="#{ticketForm.onSelect}" update=":protocolForm"/>
    <p:ajax event="rowUnselect" 
            listener="#{ticketForm.onUnselect}" update=":protocolForm"/>

    <p:column selectionMode="multiple" style="width:40px; text-align:center" />
    <!--other p:columns-->
</p:dataTable>

Managed bean:托管豆:

public void onRowSelect(SelectEvent event) {
    if (event != null && event.getObject() != null && 
        event.getObject() instanceof Ticket) {
        if (selectedTickets== null) {
            selectedTickets= new ArrayList<Ticket>();
        }
        if (!selectedTickets.contains((Ticket) event.getObject())) {
            selectedTickets.add((Ticket) event.getObject());
        }
    }
}

public void onRowUnselect(UnselectEvent event) {
    if (event != null && event.getObject() != null && 
        event.getObject() instanceof Ticket && 
        selectedTickets != null && selectedTickets.contains((Ticket) event.getObject())) {
        selectedTickets.remove((Ticket) event.getObject());
    }
}

public void onAllRowsSelect(ToggleSelectEvent event) {
    //This is the trick, you don't need receive a collection
    if (event.isSelected()) {
        selectedTickets = ticketService.getAllTickets();
    } else {
        selectedTickets = new ArrayList<Ticket>();
    }
}

LazyDataModel implemention of getRowKey method: getRowKey方法的LazyDataModel实现:

public class LazyPragaModel extends LazyDataModel<Ticket> implements Serializable {

    private TicketService ticketService;
    private static final long serialVersionUID = 1L;

    public LazyPragaModel(TicketService ticketService) {
        this.ticketService= ticketService;
    }

    @Override
    public Object getRowKey(Ticket ticket) {
        return ticket!= null ? ticket.getId() : null;
    }

    @Override
    public Praga getRowData(String rowKey) {
        List<Ticket> tickets = (List<Ticket>) getWrappedData();
        for (Ticket ticket: tickets) {
            if (ticket.getId().toString().endsWith(rowKey)) {
                return ticket;
            }
        }
        return null;
    }

    @Override
    public List<Ticket> load(int first, int pageSize, String sortField, 
                             SortOrder sortOrder, Map<String, Object> filters) {
        setRowCount(ticketService.countLazyRecords(filters).intValue());
        List<Ticket> tickets = ticketService.listLazyRecords(first, pageSize, 
                                                     sortField, sortOrder.name(), filters);
        return tickets;
    }
}

Sugestion for your service.为您的服务提供建议。 Generic methods for lazy dataTables:惰性数据表的通用方法:

public List<T> listLazyRecords(int first, int pageSize, String sortField, 
                               String sortOrder, Map<String, Object> filters) {
    sortOrder = sortOrder != null ? sortOrder.contains("ASC") ? "ASC" : 
                                    sortOrder.contains("DESC") ? "DESC" : null : null; 
    String query = " FROM " + getType().getSimpleName() + " t " + 
                  (filters.size() > 0 ? buildLazyFilters(filters) : "") + 
                  (sortOrder != null ? " ORDER BY " + sortField + " " + sortOrder : "");
    return getManager().createQuery(query, getType())
                       .setFirstResult(first).setMaxResults(pageSize).getResultList();
}

public Long countLazyRecords(Map<String, Object> filters) {
    String query = "SELECT COUNT(x) FROM " + getType().getSimpleName() + 
                   " x " + (filters.size() > 0 ? buildLazyFilters(filters) : "");
    return getManager().createQuery(query).getSingleResult();
}

private String buildLazyFilters(Map<String, Object> filters) {
    StringBuilder filterBuild = new StringBuilder("WHERE ");
    for (Map.Entry<String, Object> filter : filters.entrySet()) {
       if (filter.getValue().toString().chars().allMatch(Character::isDigit)) {
            filterBuild.append("( " + filter.getKey() + " = " + 
                                      filter.getValue() + " OR ");
       }
       filterBuild.append(filter.getKey() + " LIKE '%" + 
                          filter.getValue().toString() + "%'");
       filterBuild.append(filter.getValue().toString().chars()
                                  .allMatch(Character::isDigit) ? ") ": "");
       filterBuild.append(!filters.values().toArray()[filters.size() - 1]
                                  .equals(filter.getValue()) ? " AND " : "");
    }
    return filterBuild.toString();
}

I think you are missing some things on the datatable.我认为您在数据表上遗漏了一些东西。

Showcase: https://www.primefaces.org/showcase/ui/data/datatable/selection.xhtml展示: https ://www.primefaces.org/showcase/ui/data/datatable/selection.xhtml

You need to add selectionMode=multiple and a selection=collection to gather the selected rows like...您需要添加 selectionMode=multiple 和 selection=collection 来收集选定的行,例如...

<p:dataTable id="multipleDT" 
   var="car" 
   value="#{dtSelectionView.cars4}" 
   selectionMode="multiple" 
   selection="#{dtSelectionView.selectedCars}" 
   rowKey="#{car.id}">

Whenever you select a row or row(s) the #{dtSelectionView.selectedCars} collection will be filled with the selected rows automatically.每当您选择一行或多行时,#{dtSelectionView.selectedCars} 集合将自动填充所选行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM