Reputation: 95
I am trying to implement a comma separated keyword search using global filter in PrimeFaces.
If user types in word1,word2
in the global search, all the rows which have word1
and word2
should be returned. As of now, I was not able to find a predefined multi word search functionality for global search in PrimeFaces. Global search only works with a single keyword. Eg: Search returns results only if user types either word1
or word2
.
Seems like PrimeFaces uses client API filter() for global search. Is there a way to implement a search using multiple keywords?
<p:dataTable id="dwg" widgetVar="tblDwgDtl" var="dwgDtl"
value="#{dwgCtrlr.dwgs} sortMode="multiple" scrollable="true"
styleClass="bsa-drawing" rows="25" resizableColumns="true">
<f:facet name="header">
<p:panelGrid styleClass="ui-panelgrid-blank">
<p:row>
<p:column colspan="6">
<p:inputText id="globalFilter"
onkeyup="PF('tblDwgDtl').filter()"
placeholder="#{msg['searchAllFields.text']}" />
</p:column>
</p:row>
</p:panelGrid>
</f:facet>
Upvotes: 4
Views: 6511
Reputation: 20158
From PrimeFaces 8.0 you can use the globalFilterFunction
attribute of the p:dataTable
to implement your custom global filter. See
https://primefaces.github.io/primefaces/8_0/#/components/datatable?id=filtering
Example use:
<p:dataTable ... globalFilterFunction="#{dtFilterView.globalFilterFunction}">
...
</p:dataTable>
public boolean globalFilterFunction(Object value, Object filter, Locale locale) {
String filterText = (filter == null) ? null : filter.toString().trim().toLowerCase();
if (filterText == null || filterText.equals("")) {
return true;
}
int filterInt = getInteger(filterText);
Car car = (Car) value;
return car.getId().toLowerCase().contains(filterText)
|| car.getBrand().toLowerCase().contains(filterText)
|| car.getColor().toLowerCase().contains(filterText)
|| (car.isSold() ? "sold" : "sale").contains(filterText)
|| car.getYear() < filterInt
|| car.getPrice() < filterInt;
}
In your case of multiple words:
public boolean globalFilterFunction(Object rowValue, Object filter, Locale locale) {
String filterText = (filter == null) ? null : filter.toString();
if (filterText == null || filterText.isEmpty()) {
return true;
}
return Stream.of(filterText.split(","))
.allMatch(word -> singleWordFilter(value, word));
}
private boolean singleWordFilter(Object rowValue, String word) {
// do your single word filtering logic
}
What you could do is replace the data table renderer with a custom one. Then, in there, replace the FilterFeature
with a custom version. So, you would need extend the FilterFeature
and take care of the multiple keywords there.
Upvotes: 6