Interface PagedDataModel<E extends Identifiable<?>>

  • All Superinterfaces:
    Serializable
    All Known Implementing Classes:
    LazyPagedDataModel, NonLazyPagedDataModel

    public interface PagedDataModel<E extends Identifiable<?>>
    extends Serializable

    Paged data model specifically for <op:dataTable> which utilizes BaseEntityService from OmniPersistence project. The <op:dataTable> basically wraps the powerful PrimeFaces <p:dataTable> in a very DRY tagfile hereby further simplifying its usage and reducing down the sometimes massive boilerplate code when having a bit advanced use case of <p:dataTable> with its LazyDataModel.

    Basic Usage

    First create your entity service extending BaseEntityService from OmniPersistence project.

     @Stateless
     public class YourEntityService extends BaseEntityService<Long, YourEntity> {
    
         // ...
    
     }
     

    And make sure YourEntity extends BaseEntity or one of its subclasses from OmniPersistence project.

    
     @Entity
     public class YourEntity extends GeneratedIdEntity<Long> {
    
         private Instant created;
         private String name;
         private Type type;
         private boolean deleted;
    
         // ...
     }
     

    Then create a PagedDataModel in your backing bean as below.

     @Named
     @ViewScoped
     public class YourBackingBean implements Serializable {
    
         private PagedDataModel<YourEntity> model;
    
         @Inject
         private YourEntityService service;
    
         @PostConstruct
         public void init() {
             model = PagedDataModel.lazy(service).build();
         }
    
         public PagedDataModel<YourEntity> getModel() {
             return model;
         }
    
     }
     

    Finally use <op:dataTable> to have a semi-dynamic lazy-loaded, pageable, sortable and filterable <p:dataTable> without much hassle.

     <... xmlns:op="http://omnifaces.org/optimusfaces">
    
     <h:form id="yourEntitiesForm">
         <op:dataTable id="yourEntitiesTable" value="#{yourBackingBean.model}">
             <op:column field="id" />
             <op:column field="created" />
             <op:column field="name" />
             <op:column field="type" />
             <op:column field="deleted" />
         </op:dataTable>
     </h:form>
     

    The field attribute of <op:column> represents the entity property path. This will in turn be used in id, field, headerText and filterBy attributes of <p:column>.

    Relationships

    The <op:dataTable> supports models with OneToOne, ManyToOne, OneToMany and ElementCollection relationships. The field attribute of <op:column> can take a JavaBean path, like as you would do in EL, parent.child.subchild. Below are some examples.

    OneToOne/ManyToOne

    Given an Invoice with @OneToOne private Order order, @ManyToOne User seller and @ManyToOne User buyer:

     <op:dataTable id="invoicesTable" value="#{shop.invoices}">
         <op:column field="id" />
         <op:column field="seller.name" />
         <op:column field="order.buyer.name" />
         <op:column field="order.totalPrice" />
     </op:dataTable>
     

    OneToMany

    Given a Order with @OneToMany List<Product> products:

     <op:dataTable id="ordersTable" value="#{shop.orders}">
         <op:column field="id" />
         <op:column field="buyer.name" />
         <op:column field="totalPrice" />
         <op:column field="products.name" />
         <op:column field="products.price" />
     </op:dataTable>
     

    ElementCollection

    Given a Product with @ElementCollection List<Tag> tags:

     <op:dataTable id="productsTable" value="#{shop.products}">
         <op:column field="id" />
         <op:column field="name" />
         <op:column field="price" />
         <op:column field="tags" sortable="false" />
     </op:dataTable>
     

    Note: the @ElementCollection has currently one limitation, sorting is not supported in lazy models due to the task not being trivial in JPQL (for now). It's only supported in non-lazy models.

    DTO

    DTO subclasses of entities are also supported by providing an additional Class<DTO> resultType argument to one of the protected BaseEntityService.getPage(Page, boolean) methods.

     public class YourEntityDTO extends YourEntity {
    
         private BigDecimal totalPrice;
    
         public YourEntityDTO(Long id, String name, BigDecimal totalPrice) {
             setId(id);
             setName(name);
             this.totalPrice = totalPrice;
         }
    
         public BigDecimal getTotalPrice() {
             return totalPrice;
         }
    
     }
     
     @Stateless
     public class YourEntityService extends BaseEntityService<YourEntity> {
    
         public void getPageOfYourEntityDTO(Page page, boolean count) {
             return getPage(page, count, YourEntityDTO.class (criteriaBuilder, query, root) -> {
                 Join<YourEntityDTO, YourChildEntity> child = root.join("child");
    
                 LinkedHashMap<Getter<YourEntityDTO>, Expression<?>> mapping = new LinkedHashMap<>();
                 mapping.put(YourEntityDTO::getId, root.get("id"));
                 mapping.put(YourEntityDTO::getName, root.get("name"));
                 mapping.put(YourEntityDTO::getTotalPrice, builder.sum(child.get("price")));
    
                 return mapping;
             });
         }
    
     }
     
    Note that you must return a LinkedHashMap with Getter as key and Expression as value and that the mapping must be in exactly the same order as constructor arguments of your DTO.

    Providing specific criteria in backend

    In the backend, create a new getPageXxx() method and delegate to one of BaseEntityService.getPage(Page, boolean) methods which takes a QueryBuilder argument providing the JPA Criteria API objects to build the query with. For example, to get a page of only entities of a specific type.

     @Stateless
     public class YourEntityService extends BaseEntityService<YourEntity> {
    
         public void getPageOfFooType(Page page, boolean count) {
             return getPage(page, count, (criteriaBuilder, criteriaQuery, root) -> {
                 criteriaQuery.where(criteriaBuilder.equals(root.get("type"), Type.FOO));
             });
         }
    
     }
     

    And in the frontend, delegate to lazy(PartialResultListLoader).

     @Named
     @ViewScoped
     public class YourBackingBean implements Serializable {
    
         private PagedDataModel<YourEntity> model;
    
         @Inject
         private YourEntityService service;
    
         @PostConstruct
         public void init() {
             model = PagedDataModel.lazy(service::getPageOfFooType).build();
         }
    
         public PagedDataModel<YourEntity> getModel() {
             return model;
         }
    
     }
     

    Providing specific criteria in frontend

    Specify a method reference to a Map<Getter<E>, Object> supplier in PagedDataModel.Builder.criteria(Supplier) This way you can provide criteria from e.g. a separate form with custom filters.

     @Named
     @ViewScoped
     public class YourBackingBean implements Serializable {
    
         private PagedDataModel<YourEntity> model;
         private String searchNameStartsWith;
         private Instant searchStartDate;
         private Type[] searchTypes;
         // ...
    
         @Inject
         private YourEntityService service;
    
         @PostConstruct
         public void init() {
             model = PagedDataModel.lazy(service).criteria(this::getCriteria).build();
         }
    
         private Map<Getter<YourEntity>, Object> getCriteria() {
             Map<Getter<YourEntity>, Object> criteria = new HashMap<>();
             criteria.put(YourEntity::getName, Like.startsWith(searchNameStartsWith));
             criteria.put(YourEntity::getCreated, Order.greaterThanOrEqualTo(searchStartDate));
             criteria.put(YourEntity::getType, searchTypes);
             criteria.put(YourEntity::isDeleted, false);
             // ...
             return criteria;
         }
    
         public PagedDataModel<YourEntity> getModel() {
             return model;
         }
    
         // ...
     }
     

    You can optionally wrap the value in any Criteria, such as Like, Not, Between, Order, Enumerated, Numeric, Bool and IgnoreCase. You can even create your own ones by extending Criteria. Note that any null value is automatically interpreted as IS NULL. In case you intend to search for IS NOT NULL, use Not(null) criteria. Or in case you'd like to skip IS NULL, then simply don't add a null value to the criteria.

    Those searchNameStartsWith, searchStartDate and searchTypes in the above example can in turn be supplied via JSF input components in the same form the usual way. For example:

     <o:importConstants type="com.example.model.Type" />
    
     <p:selectManyCheckbox value="#{yourBackingBean.selectedTypes}">
         <f:selectItems value="#{Type}" />
         <p:ajax update="yourEntitiesTable" />
     </p:selectManyCheckbox>
     

    Non-lazy data model

    If you have a static list and you'd like to use <op:dataTable>, then you can use either nonLazy(List) to create a non-lazy PagedDataModel.

     @Named
     @ViewScoped
     public class YourBackingBean implements Serializable {
    
         private PagedDataModel<YourEntity> model;
    
         @PostConstruct
         public void init() {
             List<YourEntity> list = createItSomehow();
             model = PagedDataModel.nonLazy(list).build();
         }
    
         public PagedDataModel<YourEntity> getModel() {
             return model;
         }
    
     }
     

    On contrary to lazy loading, which requires the entities to be of type BaseEntity, you can here provide entities just of type Identifiable which is easier to apply on DTOs.

    Presentation

    By default, the field attribute is shown as column header text. You can optionally use head attribute of <op:column> to set the header text.

     <op:column field="id" head="ID" />
     

    You can optionally use tooltip attribute to set the tooltip of the column value.

     <op:column field="id" tooltip="The identifier" />
     

    You can optionally set rendered attribute to false to hide the column in server side.

     <op:column ... rendered="false" />
     

    You can optionally set visible attribute to false to hide the column in client side.

     <op:column ... visible="false" />
     

    The column visibility can be toggled via "Columns" dropdown button when exportable attribute of <op:dataTable> is set to true. The export button provides the options to export only visible columns, or to export all columns including invisible (but not non-rendered) columns.

     <op:dataTable ... exportable="true">
     

    Any field property which is an instance of Iterable will automatically be wrapped in an <ui:repeat>. You can always explicitly toggle this via iterable attribute.

     <op:column ... iterable="true" />
     

    Pagination

    By default, the table is paginable on 10 rows which is overrideable via rows attribute.

     <op:dataTable ... rows="20">
     

    And the table is using the following defaults as <p:dataTable> attributes which are also overrideable by specifying the very same attributes on <op:dataTable>.

    • rowsPerPage: 10,25,50
    • paginatorTemplate: {CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}
    • currentPageReportTemplate: {startRecord} - {endRecord} of {totalRecords}

    Additionally, the <op:dataTable> offers two more specific attributes which can be used to prefix and suffix the paginator report template. They are shown below with their defaults.

    • currentPageReportPrefix: Showing
    • currentPageReportSuffix: records

    Sorting

    By default, the model is sorted by Identifiable.getId() in descending order. You can override this by PagedDataModel.Builder.orderBy(Getter, boolean) passing the getter method reference and whether you want to sort ascending or not.

     @PostConstruct
     public void init() {
         model = PagedDataModel.lazy(service).orderBy(YourEntity::getName, true).build();
     }
     

    You can specify the orderBy multiple times.

     @PostConstruct
     public void init() {
         model = PagedDataModel.lazy(service).orderBy(YourEntity::getType, true).orderBy(YourEntity::getId, false).build();
     }
     

    When the ID column is nowhere specified in custom ordering, then it will still be supplied as fallback ordering.

    By default, every column is sortable. You can optionally set sortable attribute of <op:column> to false to make a column non-sortable.

     <op:column ... sortable="false" />
     

    Or if you want to make all columns non-sortable, then set sortable attribute of <op:dataTable> to false.

     <op:dataTable ... sortable="false" />
     

    This is still overrideable on specific columns by explicitly setting sortable attribute of <op:column> to true.

     <op:dataTable ... sortable="false" />
         <op:column ... />
         <op:column ... sortable="true" />
         <op:column ... />
     </op:dataTable>
     

    By default, every first sorting action on a column will sort the column ascending. You can optionally set sortDescending attribute of <op:column> to true to start descending.

     <op:column ... sortDescending="true" />
     

    Filtering

    By default, every column is filterable. In the frontend you can optionally set filterable attribute of <op:column> to false to make a column non-filterable.

     <op:column ... filterable="false" />
     

    Or if you want to make all columns non-sortable, then set filterable attribute of <op:dataTable> to false.

     <op:dataTable ... filterable="false" />
     

    This is still overrideable on specific columns by explicitly setting filterable attribute of <op:column> to true.

     <op:dataTable ... filterable="false" />
         <op:column ... />
         <op:column ... filterable="true" />
         <op:column ... />
     </op:dataTable>
     

    Note that turning off filtering applies client side only. In server side the column is still filterable via externally provided criteria, see "Providing specific criteria" sections above.

    By default, every column is filterable in "contains" mode. In the frontend you can optionally set filterMode attribute of <op:column> to startsWith, endsWith, contains or exact to set the desired filter mode.

     <op:column ... filterMode="startsWith" />
     

    By default, the filter input is represented by a free text input field. In the frontend you can optionally provide a fixed set of filter options via filterOptions attribute of <op:column>. This will be presented as a dropdown. Supported types are Object[], Collection<V> and Map<V, L>.

     <o:importConstants type="com.example.model.Type" />
     ...
     <op:column field="type" filterOptions="#{Type}" />
     

    Note that this will change the default value of filterMode from "contains" to "exact". You can still override this by explicitly specifying the filterMode attribute.

     <op:column field="type" filterOptions="#{Type}" filterMode="contains" />
     

    You can optionally turn on "global search" by setting searchable attribute of <op:dataTable> to true.

     <op:dataTable ... searchable="true">
     

    This will perform a "contains" search in every column having the field attribute, including any custom <p:column>. Note that this won't override the values of any column filters, it will just expand the filtering on them.

    On the contrary to the column filters, the global search field does not run on keyup, but only on enter key or when pressing the search button. This is done on purpose because the global search performs a relatively expensive LIKE query on every single field.

    The global search field placeholder and button label are customizable with following attributes on <op:dataTable>.

    • searchPlaceholder: Search…
    • searchButtonLabel: Search

    Exporting

    You can optionally show column toggler and CSV export buttons by setting exportable attribute of <op:dataTable> to true.

     <op:dataTable ... exportable="true">
     

    The column toggler allows you to show/hide specific columns in client side and the CSV export button with a split button allows you to export all columns or only the visible columns. The export will take into account the current filtering and sorting state, if any.

    Below are the available export related attributes and their default values.

    • columnTogglerButtonLabel: Columns
    • exportType: csv
    • exportButtonLabel: CSV
    • exportVisibleColumnsButtonLabel: Visible Columns
    • exportAllColumnsButtonLabel: All Columns
    • exportFilename: #{id}-#{of:formatDate(now, 'yyyyMMddHHmmss')}

    Note: the #{id} of the exportFilename represents the ID of the <op:dataTable>.

    By default, every column is exportable. In the frontend you can optionally set exportable attribute of <op:column> to false to make a column non-exportable, irrespective of its visibility.

     <op:column ... exportable="false" />
     

    Selection

    You can optionally make the rows selectable by setting selectable attribute of <op:dataTable> to true.

     <op:dataTable ... selectable="true">
     

    The selection is available as a List by getSelection(). The row select and unselect events will automatically update components matching PrimeFaces Selector @(.updateOnDataTableSelect). So you could automatically show the selection as below:

     <h:form id="yourEntitiesForm">
         <op:dataTable id="yourEntitiesTable" value="#{yourBackingBean.model}" selectable="true">
             <op:column field="id" />
             <op:column field="created" />
             <op:column field="name" />
             <op:column field="type" />
             <op:column field="deleted" />
         </op:dataTable>
         <p:dataTable id="selectionTable" value="#{yourBackingBean.model.selection}" var="item" styleClass="updateOnDataTableSelect">
             <op:column field="id" />
             <op:column field="created" />
             <op:column field="name" />
             <op:column field="type" />
             <op:column field="deleted" />
         </p:dataTable>
     </h:form>
     

    Note that you can't show the selection in a <op:dataTable> as the selection returns a List not a PagedDataModel. You can however keep using <op:column> the usual way as long as you use var="item" as shown above.

    You can obtain the current selection in backing bean as below:

     List<YourEntity> selection = model.getSelection();
     

    Alternatively, you can obtain all records matching the current filtering and ordering as below:

     List<YourEntity> filtered = yourEntityService.getPage(model.getPage().all(), false);
     

    Ajax events

    On every paging, sorting, filtering, searching and selection action, an ajax event will be fired. The <op:dataTable> makes use of PrimeFaces Selectors (PFS) to find components which need to be updated during those events. Below is an overview of all PFS classes recognized by <op:dataTable>.

    • updateOnDataTablePage: any JSF component with this style class will be updated on paging
    • updateOnDataTableSort: any JSF component with this style class will be updated on sorting
    • updateOnDataTableFilter: any JSF component with this style class will be updated on filtering/searching
    • updateOnDataTableSelect: any JSF component with this style class will be updated on selection

    Query parameters

    On every paging, sorting, filtering, searching and selection action the query parameter string in the URL will be updated to reflect the current table's state. Every page after the first page gets a p={pageNumber} parameter where {pageNumber} represents the current page number. Every sorting action other than the default/initial sorting gets a o={field} parameter where {field} represents the field name. If the sorting is descending, then the {field} will be prefixed with a - (a hyphen). Every filtering action gets a {field}={value} parameter where {value} represents the filter value. Every global search action gets a q={value} parameter. Every selection action gets a s={id} parameter where {id} represents the entity ID.

    You can optionally disable this behavior altogether by setting updateQueryString attribute of <op:dataTable> to false.

     <op:dataTable ... updateQueryString="false">
     

    In case you have multiple tables in same page (poor UI, but that aside), then you can optionally prefix the query parameter name with a table-specific prefix via the queryParameterPrefix attribute, so that they don't clash each other.

     <op:dataTable ... queryParameterPrefix="t1">
         ...
     </op:dataTable>
     <op:dataTable ... queryParameterPrefix="t2">
         ...
     </op:dataTable>
     

    CSS

    Standard PrimeFaces CSS is being reused as much as possible, including the fix of missing .ui-state-active class on a sorted column when sorting is done via field attribute. Below is a list of new additions:

    • .ui-datatable-actions: the div holding the global search field and export buttons
    • .ui-datatable-actions .ui-datatable-search: the span holding the global search field
    • .ui-datatable-actions .ui-datatable-export: the span holding the export buttons
    • .ui-datatable-actions .ui-inputfield.filter: the global search input field
    • .ui-datatable-actions .ui-button.search: the global search button
    • .ui-datatable-actions .ui-button.toggle: the column toggler button
    • .ui-datatable-actions .ui-splitbutton.export: the export split button
    • .ui-datatable-actions .ui-splitbutton.export .ui-button.ui-button-text-only: the export action button
    • .ui-datatable-actions .ui-splitbutton.export .ui-button.ui-splitbutton-menubutton: the export menu button

    Further, the <op:dataTable> adds three new custom classes to the table and the column:

    • .ui-datatable.empty: when the data table is empty
    • .ui-datatable .ui-sortable-column.desc: when sortDescending=true
    • .ui-datatable .ui-filter-column.global: when global search input field is focused (so you can e.g. highlight background)

    Finally, the <op:column> puts the entire cell content in a <span> which also holds the tooltip. This allows more flexible CSS control of "entire cell content" via just .ui-datatable tbody td > span.

    Adding custom action buttons

    When you want more buttons in the .ui-datatable-actions div, then you can use <ui:define name="actions"> for this.

     <op:dataTable ...>
         <ui:define name="actions">
             <p:commandButton ... />
         </ui:define>
         ...
     </op:dataTable>
     

    They will end up after the search and export buttons.

    Setting PrimeFaces-specific attributes

    In case you'd like to finetune the underlying <p:dataTable> further with additional attributes which are in turn not supported by <op:dataTable>, then you could always use <f:attribute> for that.

     <op:dataTable ...>
         <f:attribute name="caseSensitiveSort" value="#{true}" />
         <f:attribute name="reflow" value="#{true}" />
         ...
     </op:dataTable>
     

    Note that you can also just nest any <p:ajax> and even a plain <p:column> the usual way.

     <op:dataTable ...>
         <p:ajax event="page" ... />
         ...
         <p:column><p:commandLink value="Delete" ... /></p:column>
     </op:dataTable>
     

    Extending tagfiles

    In case you'd like to change the defaults of <op:dataTable>, then you can always extend it into your own tagfile like below with desired defaults supplied via <ui:param>. The below example extends it to always turn on global search and turn off column filtering.

     <ui:composition template="/optimusfaces/tags/dataTable.xhtml" xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
         <!-- Override default attribute values of op:dataTable. -->
         <ui:param name="searchable" value="true" />
         <ui:param name="filterable" value="false" />
     </ui:composition>
     

    The below example shows elaborately how you could add a new type attribute to the <op:column> which allows fine grained control over default formatting of cell content.

     <ui:composition template="/optimusfaces/tags/column.xhtml"
         xmlns="http://www.w3.org/1999/xhtml"
         xmlns:f="http://xmlns.jcp.org/jsf/core"
         xmlns:h="http://xmlns.jcp.org/jsf/html"
         xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
         xmlns:a="http://xmlns.jcp.org/jsf/passthrough"
         xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
         xmlns:o="http://omnifaces.org/ui"
         xmlns:of="http://omnifaces.org/functions"
         xmlns:p="http://primefaces.org/ui"
     >
         <!-- New custom attributes. -->
         <ui:param name="type" value="#{empty type ? 'text' : type}" /> <!-- Value MAY NOT be an EL expression referencing #{item}! -->
         <ui:param name="emptyValue" value="#{empty emptyValue ? 'n/a' : emptyValue}" />
    
         <!-- Override default attribute values. -->
         <ui:param name="head" value="#{empty head ? i18n['general.' += field] : head}" /> <!-- #{i18n} refers to the resource bundle. -->
         <ui:param name="styleClass" value="#{type}" />
    
         <ui:define name="cell">
             <c:choose>
                 <c:when test="#{type eq 'date'}">#{empty value ? emptyValue : of:formatDate(value, 'dd-MM-yyyy')}</c:when>
                 <c:when test="#{type eq 'timestamp'}">#{empty value ? emptyValue : of:formatDate(value, 'dd-MM-yyyy HH:mm:ss')}</c:when>
                 <c:when test="#{type eq 'currency'}">#{empty value ? emptyValue : of:formatCurrency(value, '$')}</c:when>
                 <c:when test="#{type eq 'percent'}">#{empty value ? emptyValue : of:formatPercent(value)}</c:when>
                 <c:when test="#{type eq 'boolean'}">#{value ? 'Y' : 'N'}</c:when>
                 <c:when test="#{type eq 'enum'}">#{empty value ? emptyValue : i18n[value['class'].simpleName += '.' += value]}</c:when>
                 <c:when test="#{type eq 'custom'}"><ui:insert /></c:when>
    
                 <!-- Add more types here! -->
    
                 <c:otherwise>#{of:coalesce(value, emptyValue)}</c:otherwise>
             </c:choose>
         </ui:define>
     </ui:composition>
     

    With both tagfiles in place, you could use them like below:

     <x:dataTable id="yourEntitiesTable" value="#{yourBackingBean.model}">
         <x:column field="id" type="custom"><a href="edit/#{item.id}" title="Edit this item">#{item.id}</a></x:column>
         <x:column field="created" type="date" />
         <x:column field="name" type="text" />
         <x:column field="type" type="enum" />
         <x:column field="deleted" type="boolean" />
     </x:dataTable>
     

    Note that the name of the EL variable representing the current item, #{item}, is predefined and cannot be changed.

    Also note that the type attribute is in above example set as a style class, so you could for example define a CSS rule to always right-align the "number" and "currency" columns.

     .ui-datatable th.number, .ui-datatable th.currency {
         text-align: right;
     }
     
    Author:
    Bauke Scholtz
    See Also:
    BaseEntityService, Page, Criteria
    • Field Detail

      • QUERY_PARAMETER_SEARCH

        static final String QUERY_PARAMETER_SEARCH
        The query parameter name representing the value of the global search query.
        See Also:
        Constant Field Values
      • QUERY_PARAMETER_PAGE

        static final String QUERY_PARAMETER_PAGE
        The query parameter name representing the current page number.
        See Also:
        Constant Field Values
      • QUERY_PARAMETER_ORDER

        static final String QUERY_PARAMETER_ORDER
        The query parameter name representing the current sort order.
        See Also:
        Constant Field Values
      • QUERY_PARAMETER_SELECTION

        static final String QUERY_PARAMETER_SELECTION
        The query parameter name representing the current selection.
        See Also:
        Constant Field Values
    • Method Detail

      • computeColumnId

        default String computeColumnId​(String field)
        Invoked when default id attribute of <op:column> is to be set. This is by default based on the field and the ID attribute does not support periods.
        Parameters:
        field - The column field.
        Returns:
        The column ID based on given field.
      • convertFilterOptionsIfNecessary

        default SelectItem[] convertFilterOptionsIfNecessary​(Object filterOptions)
        Invoked when filterOptions attribute of <op:column> is provided. Problem is, the underlying <p:column> only supports SelectItem[] or List<SelectItem>.
        Parameters:
        filterOptions - The filter options.
        Returns:
        The filter options converted to SelectItem[].
      • toggleColumn

        default void toggleColumn​(org.primefaces.event.ToggleEvent event)
        Invoked when "Columns" is adjusted.
        Parameters:
        event - Toggle event.
      • prepareExportVisible

        default void prepareExportVisible​(String tableId)
        Invoked when "Export Visible Columns" is chosen.
        Parameters:
        tableId - Table ID.
      • prepareExportAll

        default void prepareExportAll​(String tableId)
        Invoked when "Export All Columns" is chosen.
        Parameters:
        tableId - Table ID.
      • setExportable

        static void setExportable​(org.primefaces.component.column.Column column,
                                  boolean exportable)
        Remembers original value of "exportable" attribute in case it's been explicitly set.
        Parameters:
        column - The column.
        exportable - Whether it should be set exportable if not already explicitly disabled.
      • getPage

        Page getPage()
        Returns the current Page.
        Returns:
        The current Page.
      • getOrdering

        org.primefaces.model.SortMeta getOrdering()
      • getFilters

        Map<String,​org.primefaces.model.FilterMeta> getFilters()
      • getFilteredValue

        List<E> getFilteredValue()
      • setFilteredValue

        void setFilteredValue​(List<E> filteredValue)
      • getSelection

        List<E> getSelection()
      • setSelection

        void setSelection​(List<E> selection)
      • nonLazy

        static <E extends Identifiable<?>> PagedDataModel.Builder<E> nonLazy​(List<E> allData)
        Use this if you want to build a non-lazy paged data model based on given list.
        Type Parameters:
        E - The generic base entity type.
        Parameters:
        allData - List of all data.
        Returns:
        A new paged data model builder.