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>
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With