public interface PagedDataModel<E extends org.omnifaces.persistence.model.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
.
First create your entity service extending BaseEntityService
from OmniPersistence project.
@Stateless public class YourEntityService extends BaseEntityService<Long, YourEntity> { // ... }
And make sure YourEntity
extends BaseEntity
from OmniPersistence project.
@Entity public class YourEntity extends BaseEntity<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>
.
The <op:dataTable>
supports models with OneToOne
, 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.
Given an Invoice
with @OneToOne private Order order;
<op:dataTable id="invoicesTable" value="#{shop.invoices}"> <op:column field="id" /> <op:column field="seller" /> <op:column field="order.buyer" /> <op:column field="order.totalPrice" /> </op:dataTable>
Given a Order
with @OneToMany List<Product> products;
<op:dataTable id="ordersTable" value="#{shop.orders}"> <op:column field="id" /> <op:column field="buyer" /> <op:column field="totalPrice" /> <op:column field="products.name" /> <op:column field="products.price" /> </op:dataTable>
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 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.
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; } }
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>
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.
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" />
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
By default, the model is sorted by BaseEntity.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" />
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
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>
.
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.
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
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>
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
.
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>
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; }
BaseEntityService
,
Page
,
Criteria
Modifier and Type | Interface and Description |
---|---|
static class |
PagedDataModel.Builder<E extends org.omnifaces.persistence.model.Identifiable<?>>
The paged data model builder.
|
static interface |
PagedDataModel.PartialResultListLoader<E extends org.omnifaces.persistence.model.Identifiable<?>> |
Modifier and Type | Field and Description |
---|---|
static String |
QUERY_PARAMETER_ORDER
The query parameter name representing the current sort order.
|
static String |
QUERY_PARAMETER_PAGE
The query parameter name representing the current page number.
|
static String |
QUERY_PARAMETER_SEARCH
The query parameter name representing the value of the global search query.
|
static String |
QUERY_PARAMETER_SELECTION
The query parameter name representing the current selection.
|
Modifier and Type | Method and Description |
---|---|
default String |
computeColumnId(String field)
Invoked when default
id attribute of <op:column> is to be set. |
default SelectItem[] |
convertFilterOptionsIfNecessary(Object filterOptions)
Invoked when
filterOptions attribute of <op:column> is provided. |
List<E> |
getFilteredValue() |
Map<String,Object> |
getFilters() |
List<E> |
getSelection() |
static <I extends Comparable<I> & Serializable,E extends org.omnifaces.persistence.model.BaseEntity<I>> |
lazy(org.omnifaces.persistence.service.BaseEntityService<I,E> entityService)
Use this if you want to build a lazy paged data model using a
BaseEntityService . |
static <E extends org.omnifaces.persistence.model.Identifiable<?>> |
lazy(PagedDataModel.PartialResultListLoader<E> loader)
Use this if you want to build a lazy paged data model using a custom
BaseEntityService.getPage(Page, boolean) implementation. |
static <E extends org.omnifaces.persistence.model.Identifiable<?>> |
nonLazy(List<E> allData)
Use this if you want to build a non-lazy paged data model based on given list.
|
default void |
prepareExportAll(String tableId)
Invoked when "Export All Columns" is chosen.
|
default void |
prepareExportVisible(String tableId)
Invoked when "Export Visible Columns" is chosen.
|
void |
setFilteredValue(List<E> filteredValue) |
void |
setSelection(List<E> selection) |
default void |
toggleColumn(org.primefaces.event.ToggleEvent event)
Invoked when "Columns" is adjusted.
|
static final String QUERY_PARAMETER_SEARCH
static final String QUERY_PARAMETER_PAGE
static final String QUERY_PARAMETER_ORDER
static final String QUERY_PARAMETER_SELECTION
default String computeColumnId(String field)
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.field
- The column field.default SelectItem[] convertFilterOptionsIfNecessary(Object filterOptions)
filterOptions
attribute of <op:column>
is provided.
Problem is, the underlying <p:column>
only supports SelectItem[]
or
List<SelectItem>
.filterOptions
- The filter options.SelectItem[]
.default void toggleColumn(org.primefaces.event.ToggleEvent event)
event
- Toggle event.default void prepareExportVisible(String tableId)
tableId
- Table ID.default void prepareExportAll(String tableId)
tableId
- Table ID.static <I extends Comparable<I> & Serializable,E extends org.omnifaces.persistence.model.BaseEntity<I>> PagedDataModel.Builder<E> lazy(org.omnifaces.persistence.service.BaseEntityService<I,E> entityService)
BaseEntityService
.I
- The generic ID type.E
- The generic base entity type.entityService
- The entity service.static <E extends org.omnifaces.persistence.model.Identifiable<?>> PagedDataModel.Builder<E> lazy(PagedDataModel.PartialResultListLoader<E> loader)
BaseEntityService.getPage(Page, boolean)
implementation.E
- The generic base entity type.loader
- The custom BaseEntityService.getPage(Page, boolean)
implementation.static <E extends org.omnifaces.persistence.model.Identifiable<?>> PagedDataModel.Builder<E> nonLazy(List<E> allData)
E
- The generic base entity type.allData
- List of all data.Copyright © 2016–2017 OmniFaces. All rights reserved.