Since PrimeFaces does not yet support converter for <p:dataTable>
filters, I'm trying to implement my own custom filter for <p:calendar>
(of course, the design of this filter still looks somewhat ugly. It needs to apply proper CSS that I cannot).
<p:column id="discountStartDate" sortBy="#{row.discountStartDate}" style="width:140px;">
<f:facet name="header">
Start Date<br/>
<p:calendar id="startDateFilter" converter="#{dateTimeConverter}"
timeZone="Asia/Kolkata" locale="#{localeBean.locale}"
pattern="dd-MMM-yyyy hh:mm:ss a"
readonly="#{facesContext.currentPhaseId.ordinal eq 6}"
label="Start Date"
effect="slide" required="true"
size="12"
showButtonPanel="true" navigator="true">
<p:ajax event="dateSelect" listener="#{discountManagedBean.startDateListener}"
onstart="PF('blockDataTableUIWidget').block()"
oncomplete="PF('blockDataTableUIWidget').unblock()"
update="dataTable"/>
</p:calendar>
</f:facet>
<!--No need to refer to-->
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{row.discountStartDate}" converter="#{dateTimeConverter}"/>
</f:facet>
<f:facet name="input">
<p:tooltip for="dataTableTxtDiscountStartDate" value="#{messages['tooptip.dataTable.popup.calendar']}"/>
<p:calendar id="dataTableTxtDiscountStartDate" binding="#{edStartDate}" value="#{row.discountStartDate}" converter="#{dateTimeConverter}" timeZone="Asia/Kolkata" locale="#{localeBean.locale}" pattern="dd-MMM-yyyy hh:mm:ss a" readonly="#{facesContext.currentPhaseId.ordinal eq 6}" label="#{messages['discount.startdate']}" effect="explode" required="true" showButtonPanel="true" navigator="true"/>
</f:facet>
</p:cellEditor>
</p:column>
When a date is selected from the calendar, the listener specified in <p:ajax>
is invoked.
public void startDateListener(SelectEvent event)
{
if(event.getObject() instanceof DateTime)
{
//org.joda.time.DateTime
DateTime startDate=(DateTime) event.getObject();
System.out.println(startDate+" : "+startDate.getZone().getID()+ " : "+startDate.getZone());
}
}
The selected date is retrieved in this method but how can this date be used inside the load()
method? <p:dataTable>
uses org.primefaces.model.LazyDataModel<Discount>
.
Is there a way to use this date from this listener method so that the data table - <p:dataTable>
can be updated after filtering the rows based on the date supplied through the calendar - <p:calendar>
?
How can this date can be used in the overridden load()
method?
@Override
public List<Discount> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String, String> filters)
{
//Do something with filters to add the date selected from the calendar of the given filter we are talking about.
return discountService.getList(first, pageSize, multiSortMeta, filters);
}
There is a major enhancement in data table filters in PrimeFaces 5.0 final released on May 5, 2014.
PrimeFaces DataTable Filtering has been a useful feature to quickly
filter data using ajax. However there were two main limitations; it
was only based on string comparison and no support for custom
filtering implementations. Thanks to a PrimeFaces PRO sponsorship,
filtering is greatly enhanced for PF5.
Filter Facets
Filtering elements were limited to an input text and a native
dropdown, now if an input component is defined using filter facet, it
becomes the filter. This enables customizable UIs, ajax update support
for filters, using objects instead of simple strings as filter values
and more.
http://blog.primefaces.org/?p=3084
For example,
<p:column id="id" headerText="#{messages['id']}" sortBy="#{row.discountId}" filterBy="#{row.discountId}" filterMatchMode="exact">
<f:facet name="filter">
<p:inputText onkeyup="PF('dataTableUIWidget').filter();" converter="javax.faces.Long" class="ui-column-filter"/>
</f:facet>
<h:outputText value="#{row.discountId}"/>
</p:column>
discountId
would be converted to Long
by the specified converter. dataTableUIWidget
is a widgetVar
of <p:dataTable>
.
In case of LazyDataModel<T>
, the type of the Map
of filters has been changed to Map<String, Object>
(from Map<String, String>
) both the overloaded versions of the load()
method.
For single column sorting,
@Override
public List<Type> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
return super.load(first, pageSize, sortField, sortOrder, filters);
}
and for multiple columns sorting.
@Override
public List<Type> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String, Object> filters) {
return super.load(first, pageSize, multiSortMeta, sortOrder, filters);
}
As for the example in the question, it can be rewritten something like the following.
<p:column id="discountStartDate" headerText="#{messages['discount.startdate']}" filterBy="#{row.discountStartDate}" sortBy="#{row.discountStartDate}" width="200" style="text-align: right;">
<f:facet name="filter">
<p:calendar id="filterStartDate" converter="#{dateTimeConverter}"
timeZone="Asia/Kolkata" locale="#{localeBean.locale}"
pattern="dd-MMM-yyyy hh:mm:ss a"
readonly="#{facesContext.currentPhaseId.ordinal eq 6}"
label="#{messages['discount.startdate']}"
effect="slide"
size="12"
onclick="PF('filterStartDateWidget').setDate(null);PF('dataTableUIWidget').filter();"
widgetVar="filterStartDateWidget"
showButtonPanel="true" navigator="true">
<p:ajax event="dateSelect"
onstart="PF('dataTableUIWidget').filter();PF('blockDataTableUIWidget').block();"
oncomplete=" PF('blockDataTableUIWidget').unblock();"
onerror="alert('error');"/>
</p:calendar>
</f:facet>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{row.discountStartDate}" converter="#{dateTimeConverter}"/>
</f:facet>
<f:facet name="input">
<p:tooltip for="dataTableTxtDiscountStartDate" value="#{messages['tooptip.dataTable.popup.calendar']}"/>
<p:calendar id="dataTableTxtDiscountStartDate" binding="#{edStartDate}" value="#{row.discountStartDate}" converter="#{dateTimeConverter}" timeZone="Asia/Kolkata" locale="#{localeBean.locale}" pattern="dd-MMM-yyyy hh:mm:ss a" readonly="#{facesContext.currentPhaseId.ordinal eq 6}" label="#{messages['discount.startdate']}" effect="explode" required="true" showButtonPanel="true" navigator="true"/>
</f:facet>
</p:cellEditor>
</p:column>
dateTimeConverter
is a type of org.joda.time.DateTime
. Hence, the date passed through this filter will be available as org.joda.time.DateTime
after just casting from Object
taking it from the filter Map
.