---
title: Collecting Items in Containers
order: 5
layout: page
---

[[datamodel.container]]
= Collecting Items in Containers

((("[classname]#Container#", id="term.datamodel.container", range="startofrange")))


The [classname]#Container# interface is the highest containment level of the
Vaadin data model, for containing items (rows) which in turn contain properties
(columns). Containers can therefore represent tabular data, which can be viewed
in a [classname]#Table# or some other selection component, as well as
hierarchical data.

The items contained in a container are identified by an __item identifier__ or
__IID__, and the properties by a __property identifier__ or __PID__.

[[datamodel.container.intro]]
== Basic Use of Containers

The basic use of containers involves creating one, adding items to it, and
binding it as a container data source of a component.

[[datamodel.container.intro.default]]
=== Default Containers and Delegation

Before saying anything about creation of containers, it should be noted that all
components that can be bound to a container data source are by default bound to
a default container. For example, [classname]#Table# is bound to a
[classname]#IndexedContainer#, [classname]#Tree# to a
[classname]#HierarchicalContainer#, and so forth.

All of the user interface components using containers also implement the
relevant container interfaces themselves, so that the access to the underlying
data source is delegated through the component.


----
// Create a table with one column
Table table = new Table("My Table");
table.addContainerProperty("col1", String.class, null);

// Access items and properties through the component
table.addItem("row1"); // Create item by explicit ID
Item item1 = table.getItem("row1");
Property property1 = item1.getItemProperty("col1");
property1.setValue("some given value");

// Equivalent access through the container
Container container = table.getContainerDataSource();
container.addItem("row2");
Item item2 = container.getItem("row2");
Property property2 = item2.getItemProperty("col1");
property2.setValue("another given value");
----


[[datamodel.container.intro.creating]]
=== Creating and Binding a Container

A container is created and bound to a component as follows:


----
// Create a container of some type
Container container = new IndexedContainer();

// Initialize the container as required by the container type
container.addContainerProperty("name", String.class, "none");
container.addContainerProperty("volume", Double.class, 0.0);

... add items ...

// Bind it to a component
Table table = new Table("My Table");
table.setContainerDataSource(container);
----

Most components that can be bound to a container allow passing it also in the
constructor, in addition to using [methodname]#setContainerDataSource()#.
Creation of the container depends on its type. For some containers, such as the
[classname]#IndexedContainer#, you need to define the contained properties
(columns) as was done above, while some others determine them otherwise. The
definition of a property with [methodname]#addContainerProperty()# requires a
unique property ID, type, and a default value. You can also give
[parameter]#null#.

Vaadin has a several built-in in-memory container implementations, such as
[classname]#IndexedContainer# and [classname]#BeanItemContainer#, which are easy
to use for setting up nonpersistent data storages. For persistent data, either
the built-in [classname]#SQLContainer# or the [classname]#JPAContainer# add-on
container can be used.


[[datamodel.container.intro.adding]]
=== Adding Items and Accessing Properties

Items can be added to a container with the [methodname]#addItem()# method. The
parameterless version of the method automatically generates the item ID.


----
// Create an item
Object itemId = container.addItem();
----

Properties can be requested from container by first requesting an item with
[methodname]#getItem()# and then getting the properties from the item with
[methodname]#getItemProperty()#.


----
// Get the item object
Item item = container.getItem(itemId);

// Access a property in the item
Property<String> nameProperty =
        item.getItemProperty("name");

// Do something with the property
nameProperty.setValue("box");
----

You can also get a property directly by the item and property ids with
[methodname]#getContainerProperty()#.


----
container.getContainerProperty(itemId, "volume").setValue(5.0);
----


[[datamodel.container.intro.givenid]]
=== Adding Items by Given ID

Some containers, such as [classname]#IndexedContainer# and
[classname]#HierarchicalContainer#, allow adding items by a given ID, which can
be any [classname]#Object#.


----
Item item = container.addItem("agivenid");
item.getItemProperty("name").setValue("barrel");
Item.getItemProperty("volume").setValue(119.2);
----

Notice that the actual item __is not__ given as a parameter to the method, only
its ID, as the interface assumes that the container itself creates all the items
it contains. Some container implementations can provide methods to add
externally created items, and they can even assume that the item ID object is
also the item itself. Lazy containers might not create the item immediately, but
lazily when it is accessed by its ID.



[[datamodel.container.inner]]
== Container Subinterfaces

The [classname]#Container# interface contains inner interfaces that container
implementations can implement to fulfill different features required by
components that present container data.

[interfacename]#Container.Filterable#:: Filterable containers allow filtering the contained items by filters, as
described in <<datamodel.container.filtered>>.

[interfacename]#Container.Hierarchical#:: Hierarchical containers allow representing hierarchical relationships between
items and are required by the [classname]#Tree# and [classname]#TreeTable#
components. The [classname]#HierarchicalContainer# is a built-in in-memory
container for hierarchical data, and is used as the default container for the
tree components. The [classname]#FilesystemContainer# provides access to
browsing the content of a file system. Also [classname]#JPAContainer# is
hierarchical, as described in
<<dummy/../../../framework/jpacontainer/jpacontainer-usage#jpacontainer.usage.hierarchical,"Hierarchical
Container">>.

[interfacename]#Container.Indexed#:: An indexed container allows accessing items by an index number, not just their
item ID. This feature is required by some components, especially
[classname]#Table#, which needs to provide lazy access to large containers. The
[classname]#IndexedContainer# is a basic in-memory implementation, as described
in <<datamodel.container.indexedcontainer>>.

[interfacename]#Container.Ordered#:: An ordered container allows traversing the items in successive order in either
direction. Most built-in containers are ordered.

[interfacename]#Container.SimpleFilterable#:: This interface enables filtering a container by string matching with
[methodname]#addContainerFilter()#. The filtering is done by either searching
the given string anywhere in a property value, or as its prefix.

[interfacename]#Container.Sortable#:: A sortable container is required by some components that allow sorting the
content, such as [classname]#Table#, where the user can click a column header to
sort the table by the column. Some other components, such as
[classname]#Calendar#, may require that the content is sorted to be able to
display it properly. Depending on the implementation, sorting can be done only
when the [methodname]#sort()# method is called, or the container is
automatically kept in order according to the last call of the method.



See the API documentation for a detailed description of the interfaces.


[[datamodel.container.indexedcontainer]]
== [classname]#IndexedContainer#

The [classname]#IndexedContainer# is an in-memory container that implements the
[interfacename]#Indexed# interface to allow referencing the items by an index.
[classname]#IndexedContainer# is used as the default container in most selection
components in Vaadin.

The properties need to be defined with [methodname]#addContainerProperty()#,
which takes the property ID, type, and a default value. This must be done before
any items are added to the container.


----
// Create the container
IndexedContainer container = new IndexedContainer();
        
// Define the properties (columns)
container.addContainerProperty("name", String.class, "noname");
container.addContainerProperty("volume", Double.class, -1.0d);

// Add some items
Object content[][] = { {"jar", 2.0}, {"bottle", 0.75},
                       {"can", 1.5}};
for (Object[] row: content) {
    Item newItem = container.getItem(container.addItem());
    newItem.getItemProperty("name").setValue(row[0]);
    newItem.getItemProperty("volume").setValue(row[1]);
}
----

New items are added with [methodname]#addItem()#, which returns the item ID of
the new item, or by giving the item ID as a parameter as was described earlier.
Note that the [classname]#Table# component, which has
[classname]#IndexedContainer# as its default container, has a conveniency
[methodname]#addItem()# method that allows adding items as object vectors
containing the property values.

The container implements the [interfacename]#Container.Indexed# feature to allow
accessing the item IDs by their index number, with [methodname]#getIdByIndex()#,
etc. The feature is required mainly for internal purposes of some components,
such as [classname]#Table#, which uses it to enable lazy transmission of table
data to the client-side.


[[datamodel.container.beancontainer]]
== [classname]#BeanContainer#

The [classname]#BeanContainer# is an in-memory container for JavaBean objects.
Each contained bean is wrapped inside a [classname]#BeanItem# wrapper. The item
properties are determined automatically by inspecting the getter and setter
methods of the class. This requires that the bean class has public visibility,
local classes for example are not allowed. Only beans of the same type can be
added to the container.

The generic has two parameters: a bean type and an item identifier type. The
item identifiers can be obtained by defining a custom resolver, using a specific
item property for the IDs, or by giving item IDs explicitly. As such, it is more
general than the [classname]#BeanItemContainer#, which uses the bean object
itself as the item identifier, making the use usually simpler. Managing the item
IDs makes [classname]#BeanContainer# more complex to use, but it is necessary in
some cases where the [methodname]#equals()# or [methodname]#hashCode()# methods
have been reimplemented in the bean.


----
// Here is a JavaBean
public class Bean implements Serializable {
    String name;
    double energy; // Energy content in kJ/100g
    
    public Bean(String name, double energy) {
        this.name   = name;
        this.energy = energy;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public double getEnergy() {
        return energy;
    }
    
    public void setEnergy(double energy) {
        this.energy = energy;
    }
}

void basic(VerticalLayout layout) {
    // Create a container for such beans with
    // strings as item IDs.
    BeanContainer<String, Bean> beans =
        new BeanContainer<String, Bean>(Bean.class);
    
    // Use the name property as the item ID of the bean
    beans.setBeanIdProperty("name");

    // Add some beans to it
    beans.addBean(new Bean("Mung bean",   1452.0));
    beans.addBean(new Bean("Chickpea",    686.0));
    beans.addBean(new Bean("Lentil",      1477.0));
    beans.addBean(new Bean("Common bean", 129.0));
    beans.addBean(new Bean("Soybean",     1866.0));

    // Bind a table to it
    Table table = new Table("Beans of All Sorts", beans);
    layout.addComponent(table);
}
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.beancontainer.basic[on-line example, window="_blank"].

To use explicit item IDs, use the methods [methodname]#addItem(Object, Object)#,
[methodname]#addItemAfter(Object, Object, Object)#, and
[methodname]#addItemAt(int, Object, Object)#.

It is not possible to add additional properties to the container, except
properties in a nested bean.

[[datamodel.container.beancontainer.nestedproperties]]
=== Nested Properties

((("nested bean properties", id="term.datamodel.container.beancontainer.nestedproperties", range="startofrange")))


If you have a nested bean with an 1:1 relationship inside a bean type contained
in a [classname]#BeanContainer# or [classname]#BeanItemContainer#, you can add
its properties to the container by specifying them with
[methodname]#addNestedContainerProperty()#. The feature is defined at the level
of [classname]#AbstractBeanContainer#.
((("[methodname]#addNestedContainerProperty()#")))

As with the bean in a bean container, also a nested bean must have public
visibility or otherwise an access exception is thrown. An intermediate reference
from a bean in the bean container to a nested bean may have a null value.

For example, let us assume that we have the following two beans with the first
one nested inside the second one.


----
/** Bean to be nested */
public class EqCoord implements Serializable {
    double rightAscension; /* In angle hours */
    double declination;    /* In degrees     */

    ... setters and getters for the properties ...
}

/** Bean referencing a nested bean */
public class Star implements Serializable {
    String  name;
    EqCoord equatorial; /* Nested bean */

    ... setters and getters for the properties ...
}
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.beanitemcontainer.nestedbean[on-line example, window="_blank"].

After creating the container, you can declare the nested properties by
specifying their property identifiers with the
[methodname]#addNestedContainerProperty()# in dot notation.


----
// Create a container for beans
BeanItemContainer<Star> stars =
    new BeanItemContainer<Star>(Star.class);

// Declare the nested properties to be used in the container
stars.addNestedContainerProperty("equatorial.rightAscension");
stars.addNestedContainerProperty("equatorial.declination");

// Add some items
stars.addBean(new Star("Sirius",  new EqCoord(6.75, 16.71611)));
stars.addBean(new Star("Polaris", new EqCoord(2.52, 89.26417)));

// Here the nested bean reference is null
stars.addBean(new Star("Vega", null));
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.beanitemcontainer.nestedbean[on-line example, window="_blank"].

If you bind such a container to a [classname]#Table#, you probably also need to
set the column headers. Notice that the entire nested bean itself is still a
property in the container and would be displayed in its own column. The
[methodname]#toString()# method is used for obtaining the displayed value, which
is by default an object reference. You normally do not want this, so you can
hide the column with [methodname]#setVisibleColumns()#.
((("[methodname]#setVisibleColumns()#")))


----
// Put them in a table
Table table = new Table("Stars", stars);
table.setColumnHeader("equatorial.rightAscension", "RA");
table.setColumnHeader("equatorial.declination",    "Decl");
table.setPageLength(table.size());

// Have to set explicitly to hide the "equatorial" property
table.setVisibleColumns("name",
    "equatorial.rightAscension", "equatorial.declination");
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.beanitemcontainer.nestedbean[on-line example, window="_blank"].

The resulting table is shown in
<<figure.datamodel.container.beancontainer.nestedproperties>>.

[[figure.datamodel.container.beancontainer.nestedproperties]]
.[classname]#Table# Bound to a [classname]#BeanContainer# with Nested Properties
image::img/beanitemcontainer-nested-beans.png[]

The bean binding in [classname]#AbstractBeanContainer# normally uses the
[classname]#MethodProperty# implementation of the [classname]#Property#
interface to access the bean properties using the setter and getter methods. For
nested properties, the [classname]#NestedMethodProperty# implementation is used.
((("[classname]#MethodProperty#")))
((("[classname]#NestedMethodProperty#")))

(((range="endofrange", startref="term.datamodel.container.beancontainer.nestedproperties")))

ifdef::web[]
[[datamodel.container.beancontainer.idresolver]]
=== Defining a Bean ID Resolver

If a bean ID resolver is set using [methodname]#setBeanIdResolver()# or
[methodname]#setBeanIdProperty()#, the methods [methodname]#addBean()#,
[methodname]#addBeanAfter()#, [methodname]#addBeanAt()# and
[methodname]#addAll()# can be used to add items to the container. If one of
these methods is called, the resolver is used to generate an identifier for the
item (must not return [parameter]#null#).

Note that explicit item identifiers can also be used when a resolver has been
set by calling the [methodname]#addItem*()# methods - the resolver is only used
when adding beans using the [methodname]#addBean*()# or
[methodname]#addAll(Collection)# methods.

endif::web[]


[[datamodel.container.beanitemcontainer]]
== [classname]#BeanItemContainer#

[classname]#BeanItemContainer# is a container for JavaBean objects where each
bean is wrapped inside a [classname]#BeanItem# wrapper. The item properties are
determined automatically by inspecting the getter and setter methods of the
class. This requires that the bean class has public visibility, local classes
for example are not allowed. Only beans of the same type can be added to the
container.

[classname]#BeanItemContainer# is a specialized version of the
[classname]#BeanContainer# described in <<datamodel.container.beancontainer>>.
It uses the bean itself as the item identifier, which makes it a bit easier to
use than [classname]#BeanContainer# in many cases. The latter is, however,
needed if the bean has reimplemented the [methodname]#equals()# or
[methodname]#hashCode()# methods.

Let us revisit the example given in <<datamodel.container.beancontainer>> using
the [classname]#BeanItemContainer#.


----
// Create a container for the beans
BeanItemContainer<Bean> beans =
    new BeanItemContainer<Bean>(Bean.class);
    
// Add some beans to it
beans.addBean(new Bean("Mung bean",   1452.0));
beans.addBean(new Bean("Chickpea",    686.0));
beans.addBean(new Bean("Lentil",      1477.0));
beans.addBean(new Bean("Common bean", 129.0));
beans.addBean(new Bean("Soybean",     1866.0));

// Bind a table to it
Table table = new Table("Beans of All Sorts", beans);
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.beanitemcontainer.basic[on-line example, window="_blank"].

It is not possible to add additional properties to a
[classname]#BeanItemContainer#, except properties in a nested bean, as described
in <<datamodel.container.beancontainer>>. ((("nested bean
properties")))


ifdef::web[]
[[datamodel.container.iterating]]
== Iterating Over a Container

As the items in a [classname]#Container# are not necessarily indexed, iterating
over the items has to be done using an [classname]#Iterator#. The
[methodname]#getItemIds()# method of [classname]#Container# returns a
[classname]#Collection# of item identifiers over which you can iterate. The
following example demonstrates a typical case where you iterate over the values
of check boxes in a column of a [classname]#Table# component. The context of the
example is the example used in
<<dummy/../../../framework/components/components-table#components.table,"Table">>.


----
// Collect the results of the iteration into this string.
String items = "";

// Iterate over the item identifiers of the table.
for (Iterator i = table.getItemIds().iterator(); i.hasNext();) {
    // Get the current item identifier, which is an integer.
    int iid = (Integer) i.next();
    
    // Now get the actual item from the table.
    Item item = table.getItem(iid);
    
    // And now we can get to the actual checkbox object.
    Button button = (Button)
            (item.getItemProperty("ismember").getValue());
    
    // If the checkbox is selected.
    if ((Boolean)button.getValue() == true) {
        // Do something with the selected item; collect the
        // first names in a string.
        items += item.getItemProperty("First Name")
                     .getValue() + " ";
    }
}

// Do something with the results; display the selected items.
layout.addComponent (new Label("Selected items: " + items));
----

Notice that the [methodname]#getItemIds()# returns an __unmodifiable
collection__, so the [classname]#Container# may not be modified during
iteration. You can not, for example, remove items from the
[classname]#Container# during iteration. The modification includes modification
in another thread. If the [classname]#Container# is modified during iteration, a
[classname]#ConcurrentModificationException# is thrown and the iterator may be
left in an undefined state.

endif::web[]

[[datamodel.container.gpc]]
== [classname]#GeneratedPropertyContainer#

[classname]#GeneratedPropertyContainer# is a container wrapper that allows
defining generated values for properties (columns). The generated properties can
shadow properties with the same IDs in the wrapped container. Removing a
property from the wrapper hides it.

The container is especially useful with [classname]#Grid#, which does not
support generated columns or hiding columns like [classname]#Table# does.

[[datamodel.container.gpc.wrapping]]
=== Wrapping a Container

A container to be wrapped must be a [interfacename]#Container.Indexed#. It can
optionally also implement [interfacename]#Container.Sortable# or
[interfacename]#Container.Filterable# to enable sorting and filtering the
container, respectively.

For example, let us consider the following container with some regular columns:


----
IndexedContainer container = new IndexedContainer();
container.addContainerProperty("firstname", String.class, null);
container.addContainerProperty("lastname", String.class, null);
container.addContainerProperty("born", Integer.class, null);
container.addContainerProperty("died", Integer.class, null);

// Wrap it
GeneratedPropertyContainer gpcontainer =
    new GeneratedPropertyContainer(container);
----


[[datamodel.container.gpc.properties]]
=== Generated Properties

Now, you can add generated properties in the container with
[methodname]#addGeneratedProperty()# by specifying a property ID and a
[interfacename]#PropertyValueGenerator#. The method takes the ID of the
generated property as first parameter; you can use a same ID as in the wrapped
container to shadow its properties.

You need to implement [methodname]#getType()#, which must return the class
object of the value type of the property, and [methodname]#getValue()#, which
returns the property value for the given item. The item ID and the property ID
of the generated property are also given in case they are needed. You can access
other properties of the item to compute the property value.


----
gpcontainer.addGeneratedProperty("lived",
    new PropertyValueGenerator<Integer>() {
    @Override
    public Integer getValue(Item item, Object itemId,
                            Object propertyId) {
        int born = (Integer)
                   item.getItemProperty("born").getValue();
        int died = (Integer)
                   item.getItemProperty("died").getValue();
        return Integer.valueOf(died - born);
    }

    @Override
    public Class<Integer> getType() {
        return Integer.class;
    }
});
----

You can access other items in the container, also their generated properties,
although you should beware of accidental recursion.


[[datamodel.container.gpc.using]]
=== Using [classname]#GeneratedPropertyContainer#

Finally, you need to bind the [classname]#GeneratedPropertyContainer# to the
component instead of the wrapped container.


----
Grid grid = new Grid(gpcontainer);
----

When using [classname]#GeneratedPropertyContainer# in [classname]#Grid#, notice
that generated columns are read-only, so you can not add grid rows with
[methodname]#addRow()#. In editable mode, editor fields are not generated for
generated columns.


[[datamodel.container.gpc.sorting]]
=== Sorting

Even though the [classname]#GeneratedPropertyContainer# implements
[interfacename]#Container.Sortable#, the wrapped container must also support it
or otherwise sorting is disabled. Also, the generated properties are not
normally sortable, but require special handling to enable sorting.



[[datamodel.container.filtered]]
== [classname]#Filterable# Containers

((("Container", "Filterable", id="term.datamodel.container.filtered.filterable", range="startofrange")))


((("[classname]#Filter# (in [classname]#Container#)", id="term.datamodel.container.filtered.filters", range="startofrange")))


Containers that implement the [classname]#Container.Filterable# interface can be
filtered. For example, the built-in [classname]#IndexedContainer# and the bean
item containers implement it. Filtering is typically used for filtering the
content of a [classname]#Table#.
((("[classname]#IndexedContainer#")))
((("[classname]#Table#")))

Filters implement the [classname]#Filter# interface and you add them to a
filterable container with the [methodname]#addContainerFilter()# method.
Container items that pass the filter condition are kept and shown in the
filterable component.
((("[methodname]#addContainerFilter()#")))


----
Filter filter = new SimpleStringFilter("name",
        "Douglas", true, false);
table.addContainerFilter(filter);
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.filter.basic[on-line example, window="_blank"].

If multiple filters are added to a container, they are evaluated using the
logical AND operator so that only items that are passed by all the filters are
kept.

[[datamodel.container.filtered.composite]]
=== Atomic and Composite Filters

Filters can be classified as __atomic__ and __composite__. Atomic filters, such
as [classname]#SimpleStringFilter#, define a single condition, usually for a
specific container property. Composite filters make filtering decisions based on
the result of one or more other filters. The built-in composite filters
implement the logical operators AND, OR, or NOT.

For example, the following composite filter would filter out items where the
[literal]#++name++# property contains the name "Douglas" somewhere __or__ where
the [literal]#++age++# property has value less than 42. The properties must have
[classname]#String# and [classname]#Integer# types, respectively.


----

filter = new Or(new SimpleStringFilter("name",
        "Douglas", true, false),
        new Compare.Less("age", 42));
----


[[datamodel.container.filtered.builtin]]
=== Built-In Filter Types

The built-in filter types are the following:

[classname]#SimpleStringFilter#:: ((("[classname]#SimpleStringFilter#")))
+
Passes items where the specified property, that must be of [classname]#String#
type, contains the given [parameter]#filterString# as a substring. If
[parameter]#ignoreCase# is [parameter]#true#, the search is case insensitive. If
the [parameter]#onlyMatchPrefix# is [parameter]#true#, the substring may only be
in the beginning of the string, otherwise it may be elsewhere as well.

[classname]#IsNull#:: ((("[classname]#IsNull# (filter)")))
+
Passes items where the specified property has null value. For in-memory
filtering, a simple [literal]#++==++# check is performed. For other containers,
the comparison implementation is container dependent, but should correspond to
the in-memory null check.

[classname]#Equal#, [classname]#Greater#, [classname]#Less#, [classname]#GreaterOrEqual#, and [classname]#LessOrEqual#:: ((("[classname]#Equal# (filter)")))
((("[classname]#Greater# (filter)")))
((("[classname]#Less# (filter)")))
((("[classname]#GreaterOrEqual# (filter)")))
((("[classname]#LessOrEqual# (filter)")))
The comparison filter implementations compare the specified property value to
the given constant and pass items for which the comparison result is true. The
comparison operators are included in the abstract [classname]#Compare# class.

+
For the [classname]#Equal# filter, the [methodname]#equals()# method for the
property is used in built-in in-memory containers. In other types of containers,
the comparison is container dependent and may use, for example, database
comparison operations.

+
For the other filters, the property value type must implement the
[classname]#Comparable# interface to work with the built-in in-memory
containers. Again for the other types of containers, the comparison is container
dependent.

[classname]#And# and [classname]#Or#:: ((("[classname]#And# (filter)")))
((("[classname]#Or# (filter)")))
+
These logical operator filters are composite filters that combine multiple other
filters.

[classname]#Not#:: ((("[classname]#Not# (filter)")))
+
The logical unary operator filter negates which items are passed by the filter
given as the parameter.

[[datamodel.container.filtered.custom]]
=== Implementing Custom Filters

A custom filter needs to implement the [classname]#Container.Filter# interface.

A filter can use a single or multiple properties for the filtering logic. The
properties used by the filter must be returned with the
[methodname]#appliesToProperty()# method. If the filter applies to a
user-defined property or properties, it is customary to give the properties as
the first argument for the constructor of the filter.


----
class MyCustomFilter implements Container.Filter {
    protected String propertyId;
    protected String regex;
    
    public MyCustomFilter(String propertyId, String regex) {
        this.propertyId = propertyId;
        this.regex      = regex;
    }

    /** Tells if this filter works on the given property. */
    @Override
    public boolean appliesToProperty(Object propertyId) {
        return propertyId != null &&
               propertyId.equals(this.propertyId);
    }
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.filter.custom[on-line example, window="_blank"].

The actual filtering logic is done in the [methodname]#passesFilter()# method,
which simply returns [literal]#++true++# if the item should pass the filter and
[literal]#++false++# if it should be filtered out.


----
    /** Apply the filter on an item to check if it passes. */
    @Override
    public boolean passesFilter(Object itemId, Item item)
            throws UnsupportedOperationException {
        // Acquire the relevant property from the item object
        Property p = item.getItemProperty(propertyId);
        
        // Should always check validity
        if (p == null || !p.getType().equals(String.class))
            return false;
        String value = (String) p.getValue();
        
        // The actual filter logic
        return value.matches(regex);
    }
}
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.filter.custom[on-line example, window="_blank"].

You can use such a custom filter just like any other:


----
c.addContainerFilter(
    new MyCustomFilter("Name", (String) tf.getValue()));
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#datamodel.container.filter.custom[on-line example, window="_blank"].


(((range="endofrange", startref="term.datamodel.container.filtered.filters")))
(((range="endofrange", startref="term.datamodel.container.filtered.filterable")))

(((range="endofrange", startref="term.datamodel.container")))


