Пользовательские фильтры и конвертеры в p:dataTable
Поскольку PrimeFaces еще не поддерживает конвертер для <p:dataTable>
фильтры, я пытаюсь реализовать свой собственный фильтр для <p:calendar>
(конечно, дизайн этого фильтра все еще выглядит несколько уродливо. Он должен применять правильный CSS, который я не могу).
<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>
Когда дата выбирается из календаря, слушатель, указанный в <p:ajax>
вызывается.
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());
}
}
Выбранная дата извлекается в этом методе, но как эту дату можно использовать внутри load()
метод? <p:dataTable>
использования org.primefaces.model.LazyDataModel<Discount>
,
Есть ли способ использовать эту дату из этого метода слушателя, чтобы таблица данных - <p:dataTable>
может быть обновлено после фильтрации строк на основе даты, указанной в календаре - <p:calendar>
?
Как эту дату можно использовать в переопределенной load()
метод?
@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);
}
1 ответ
В финальной версии PrimeFaces 5.0, выпущенной 5 мая 2014 года, значительно улучшены фильтры таблиц данных.
PrimeFaces DataTable Filtering была полезной функцией для быстрой фильтрации данных с использованием ajax. Однако было два основных ограничения; оно основывалось только на сравнении строк и не поддерживало пользовательских реализаций фильтрации. Благодаря спонсорской поддержке PrimeFaces PRO фильтрация для PF5 значительно улучшена.
Фасеты фильтра
Фильтрующие элементы были ограничены входным текстом и собственным выпадающим списком, теперь, если входной компонент определен с использованием фасета фильтра, он становится фильтром. Это позволяет настраивать пользовательский интерфейс, поддержку обновления ajax для фильтров, использовать объекты вместо простых строк в качестве значений фильтра и многое другое.
http://blog.primefaces.org/?p=3084
Например,
<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
будет преобразован в Long
указанным конвертером. dataTableUIWidget
это widgetVar
из <p:dataTable>
,
В случае LazyDataModel<T>
тип Map
фильтров был изменен на Map<String, Object>
(от Map<String, String>
) обе перегруженные версии load()
метод.
Для сортировки по одному столбцу,
@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);
}
и для сортировки нескольких столбцов.
@Override
public List<Type> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String, Object> filters) {
return super.load(first, pageSize, multiSortMeta, sortOrder, filters);
}
Что касается примера в вопросе, его можно переписать примерно так:
<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
это тип org.joda.time.DateTime
, Следовательно, дата, прошедшая через этот фильтр, будет доступна как org.joda.time.DateTime
только после кастинга Object
извлекая его из фильтра Map
,