【问题标题】:PrimeFaces Datatable: How to receive selected rows values?PrimeFaces Datatable:如何接收选定的行值?
【发布时间】:2019-01-10 07:45:26
【问题描述】:

已编辑:未提供完整信息。

我使用 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" />

更具体地说,选择“选择”标题“复选框时,我希望在服务器端接收所有选定的行数据并使用每行的ID。此外,当至少一个复选框被选中时,还有一些逻辑有助于解决隐藏/呈现页面按钮的目标。为此,我需要在按下按钮时手动拦截行/复选框选择事件并从中记录 ID,因此我不能使用这种逻辑使用 dataTable 的 selection 属性。 在服务器端,我有几个事件监听器。 :

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
}

不幸的是,ToggleSelectEvent 仅包含有关数据表本身的信息。没有关于我找不到的行的信息。我还尝试添加 process="@this" partialSubmit="true" 属性,但似乎它们执行不同的操作。

那么,您能否举例说明如何从事件对象中检索此类数据?我应该使用其他方法来解决它吗?提前感谢您的回答。

【问题讨论】:

    标签: primefaces jsf-2


    【解决方案1】:

    我认为你在数据表上遗漏了一些东西。

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

    您需要添加 selectionMode=multiple 和 selection=collection 来收集选定的行,例如...

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

    每当您选择一行或多行时,#{dtSelectionView.selectedCars} 集合将自动填充所选行。

    【讨论】:

    • 带复选框的选择不需要 selectionMode="multiple"。此参数仅用于在按住 CTRL 键单击表格行时进行多选。
    【解决方案2】:

    您使用的是惰性数据表,这不会在页面更改时保留选择。

    1. 您需要将 selection 参数设置为您的集合类型

    2. 在您的LazyDataModel 中实现getRowKey 并删除rowKey="#{ticket.id}"

    3. 复选框选择不需要selectionMode="multiple"。

      • 此参数仅用于在按住 CTRL 键单击表格行时进行多选
    4. 我的建议是手动控制您选择的数据

    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>
    

    托管 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>();
        }
    }
    

    LazyDataModelgetRowKey方法的实现:

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

    对您的服务的建议。惰性数据表的通用方法:

    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();
    }
    

    【讨论】:

      猜你喜欢
      • 2012-11-07
      • 2018-03-24
      • 1970-01-01
      • 2014-02-25
      • 1970-01-01
      • 2017-02-20
      • 1970-01-01
      • 2021-12-31
      • 2015-12-23
      相关资源
      最近更新 更多