-
Notifications
You must be signed in to change notification settings - Fork 15
CompositeFilter 2.x
TOCSTART
TOCEND
The CompositeFilter component allows user to build complex filter criteria with various filter conditions. It provides its own criteria API that can be easily adapted for different use-cases. There are two ready-to-use solutions for in memory filtering over collections and building Hibernate criteria. Also, CompositeFilter can be integrated with DataTable and TreeTable components and serve as an external filter in addition to column filtering options.
- Type-specific editors
- In-memory collections filtering
- Hibernate Criteria builder
- DataTable and TreeTable integration
- i18n support
The CompositeFilter component can be defined using the <o:compositeFilter> tag with a set of <o:filterProperty> tags inside. Each <o:filterProperty> tag defines one property that will be available to the user when building filter criteria. Here's a simple example:
<o:compositeFilter id="filter" value="#{CompositeFilterBean.criteria}"> <o:filterProperty value="Artist" name="artist"/> <o:filterProperty value="Album" name="album"/> <o:filterProperty value="Kind" name="kind"/> </o:compositeFilter>
The value attribute of <o:filterProperty> defines property title as it will be represented in property selector. The name attribute is used to specify property name and corresponds to name of the field in the data class or column name in the database.
The CompositeFilter component supports different types of filter properties. The type attribute of <o:filterProperty> tag defines which of the predefined filter types should be used. It can take the following values: "text", "number", "select", and "date". The default value is "text". The type determines a set of operations for the property and the kind of parameter editor.
Filter Type | Operations | Editor |
---|---|---|
"text" | equals, contains, beginsWith, endsWith | HtmlInputText |
"number" | equals, lessOrEqual, greaterOrEqual, less, greater, between | Spinner |
"select" | equals | DropDownField |
"date" | equals, lessOrEqual, greaterOrEqual, less, greater, between | DateChooser |
The <o:filterProperty> tag provides additional attributes for editor customizations:
Attribute | Filter Type | Description |
---|---|---|
converter | all filter types | The converter instance to be registered for this component |
dataProvider | text, select | List of possible values list that will be displayed in drop down |
maxValue | number | Maximum value for Spinner editor |
minValue | number | Minimum value for Spinner editor |
step | number | The amount by which the value is increased/decreased |
timeZone | date | Time zone in which to interpret the time information in the date |
pattern | date | Date pattern similar to that in the java.text.SimpleDateFormat class |
caseSensitive | text | Whether search is case sensitive |
FilterCriterion class is designed to represent a model for the CompositeFilter component. The value attribute of the <o:compositeFilter> tag is used to the specify initial set of filter criteria and a value holder for the result of user's input. The CompositeFilter provides the following utility classes – PredicateBuilder for in memory filtering over collections and HibernateCriterionBuilder for building Hibernate criteria. The example below demostrates two ways of filtering using FilterCriterion.
<o:compositeFilter id="cf" value="#{CompositeFilterBean.criteria}" > <o:filterProperty name="firstName" value="First Name" type="text"/> <o:filterProperty value="age" type="number"/> <o:filterProperty name="dateOfBirth" value="Date Of Birth" type="date" pattern="dd-MM-yyyy" timeZone="GMT"/> <o:filterProperty name="placeOfBirth.country" value="Country" type="select" dataProvider="#{CompositeFilterBean.countries}" converter="#{CompositeFilterBean.countryConverter}"/> </o:compositeFilter>
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Predicate; import org.hibernate.criterion.Criterion; ... public class CompositeFilterBean {private List<User> customers; private List<User> filteredCustomers; private List<User> employees; private CompositeFilterCriterion criteria;
...
public void setCriteria(CompositeFilterCriterion criteria) { this.criteria = criteria;
Predicate predicate = PredicateBuilder.build(criteria); filteredCustomers = <span class="code-keyword">new</span> ArrayList<User>(customers); CollectionUtils.filter(filteredCustomers, predicate); Criterion criterion = HibernateCriterionBuilder.build(criteria); employees = userService.findByCriterion(criterion);
}
... }
public class UserService extends HibernateDaoSupport{public Collection<User> findByCriterion(Criterion criterion) { Criteria criteria = getSession().createCriteria(User.class); criteria.add(criterion); return (List<User>) criteria.list(); } }
The CompositeFilter component can be attached to the DataTable or TreeTable component using the for attribute of <o:compositeFilter> tag. This means that the data in the DataTable (or TreeTable) will be automatically filtered with criteria defined by user using the CompositeFilter. Furthermore the CompositeFilter will automatically detect table columns and provide them to a user as a basis for filters construction, which removes the need to specify the <o:filterProperty> tags when CompositeFilter is bound to a DataTable or TreeTable. This autodetection mode can be turned off by by assigning false to the autoDetect attribute (the default value is true), which makes it possible to customize the list of fields available for filtering or their parameters.
It's possible to attach CompositeFilter to a DataTable/TreeTable component even if that component already has other filters attached.
The example below shows two composite filter components attached to the same DataTable in both modes (with auto detection mode on and off). Both components will have the same appearance and behavior, and the same set of properties with the same types.
<o:compositeFilter id="filter1" for="banks"/><o:compositeFilter id="filter2" for="banks" autoDetect="false"> <o:filterProperty name="institutionName" value="Institution Name" type="text"/> <o:filterProperty name="state" value="State" type="select" dataProvider="#{StateList.values}" converter="#{StatesList.converter}"/> <o:filterProperty name="foundationDate" value="Founded" type="date"> <f:convertDateTime pattern="MM/yyyy"/> </o:filterProperty> </o:compositeFilter>
<o:dataTable id="banks" var="bank" value="#{BanksList.banks}"> <o:column id="institutionName"> <f:facet name="header"> <h:outputText value="Institution Name"/> </f:facet> <h:outputText value="#{bank.institutionName}"/> </o:column> <o:column id="state" header="State"> <h:outputText value="#{bank.state}" converter="#{StatesList.converter}"/> </o:column> <o:column id="foundationDate"> <f:facet name="header"> <h:outputText value="Founded"/> </f:facet> <h:outputText value="#{bank.foundationDate}"> <f:convertDateTime pattern="MM/yyyy"/> </h:outputText> </o:column> </o:dataTable>
When the CompositeFilter component is bound to a DataTable (or TreeTable) component, it displays the "Apply" button, which allows filtering the attached DataTable (or TreeTable). The text and appearance of this button can be customized by using the "applyButton" facet. You can place any UICommand component in this facet, for example <h:commandButton> or <h:commandLink> and configure their attributes according to your needs.
CompositeFilter provides ability to easily localize operation labels by specifying labels attribute <o:compositeFilter> tag and providing proper message bundle. The resource bundle should contain messages for each operation and have the following form:
org.openfaces.filter.condition.equals=Equals org.openfaces.filter.condition.contains=Contains org.openfaces.filter.condition.beginsWith=Begins with org.openfaces.filter.condition.endsWith=Ends with org.openfaces.filter.condition.lessOrEqual=<= org.openfaces.filter.condition.greaterOrEqual=>= org.openfaces.filter.condition.greater=> org.openfaces.filter.condition.less=< org.openfaces.filter.condition.between=Between
<o:loadBundle basename="com.mycompany.testapp.filter.MessageResources" var="messages"/><o:compositeFilter id="compositeFilter" value="#{CompositeFilterBean.criteria}" labels="#{messages}"> <o:filterProperty name="title" value="Book Title" type="text"/> <o:filterProperty name="published" value="Date" type="date" pattern="yyyy"/> </o:compositeFilter>
All client-side API methods for the CompositeFilter component are listed below:
Method | Description |
---|---|
add() | Adds new filter row for CompositeFilter component on which this method is invoked. |
remove(index) | Removes filter row with specified index from CompositeFilter component on which this method is invoked. |
clear() | Removes all filter rows from CompositeFilter component on which this method is invoked. |