123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834 |
- ---
- 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")))
-
|