ソースを参照

BoV: Updated selection components to Vaadin 8.

Change-Id: Idb4fff857bcdf9d33ecb8d4fd3062ffea96d5391
feature/eventbus
Sami Ekblad 7年前
コミット
143822de9b
1個のファイルの変更154行の追加276行の削除
  1. 154
    276
      documentation/components/components-selection.asciidoc

+ 154
- 276
documentation/components/components-selection.asciidoc ファイルの表示

@@ -36,181 +36,103 @@ They also inherit [classname]#AbstractSelect#.
[[components.selection.databinding]]
== Binding Selection Components to Data

The selection components are strongly coupled with the Vaadin Data Model,
described in
The selection components typically bound to list of items obtained from backend system.
You can give the the list of items in the constructor or set it set
[methodname]#setItems()#. Read more in
<<dummy/../../../framework/datamodel/datamodel-overview.asciidoc#datamodel.overview,"Binding
Components to Data">>. The selectable items in all selection components are
objects that implement the [classname]#Item# interface. The items are contained
in a [classname]#Container#.

All selection components are containers themselves and simply forward all
container operations to the underlying container data source. You can give the
container in the constructor or set it set
[methodname]#setContainerDataSource()#. This is further described in
<<dummy/../../../framework/datamodel/datamodel-container#datamodel.container.intro,"Basic
Use of Containers">>.


[source, java]
----
// Have a container data source of some kind
IndexedContainer container = new IndexedContainer();
container.addContainerProperty("name", String.class, null);
...

// Create a selection component bound to the container
OptionGroup group = new OptionGroup("My Select", container);
----

If you do not bind a selection component to a container data source, a default
container is used. It is usually either an [classname]#IndexedContainer# or a
[classname]#HierarchicalContainer#.

The current selection of a selection component is bound to the
[classname]#Property# interface, so you can get the current selection as the
value of the selection component. Also selection changes are handled as value
change events, as is described later.
Components to Data">>.

You can get the current selection as the
value of the selection component using [methodname]#getSelected# defined in
[interfacename]#Select# interface. Also selection changes are handled as
selection change events, as is described later.

[[components.selection.adding]]
== Adding New Items

New items are added with the [methodname]#addItem()# method defined in the
[classname]#Container# interface, described in
<<dummy/../../../framework/datamodel/datamodel-container#datamodel.container.intro,"Basic
Use of Containers">>.


[source, java]
----
// Create a selection component
ComboBox select = new ComboBox("My ComboBox");

// Add items with given item IDs
select.addItem("Mercury");
select.addItem("Venus");
select.addItem("Earth");
----

The [methodname]#addItem()# method creates an empty [classname]#Item#, which is
identified by its __item identifier__ (IID) object, given as the parameter. This
item ID is by default used also as the caption of the item, as described in more
detail later.

We emphasize that [methodname]#addItem()# is a factory method that __takes an
item ID, not the actual item__ as the parameter - the item is returned by the
method. The item is of a type that is specific to the container and has itself
little relevance for most selection components, as the properties of an item may
not be used in any way (except in [classname]#Table#), only the item ID.

The item identifier is typically a string, in which case it can be used as the
caption, but can be any object type. We could as well have given integers for
the item identifiers and set the captions explicitly with
[methodname]#setItemCaption()#. You could also add an item with the
parameterless [methodname]#addItem()#, which returns an automatically generated
item ID.

New items are added with the [methodname]#addItems()# method.

[source, java]
----
// Create a selection component
ComboBox select = new ComboBox("My Select");
ComboBox<String> select = new ComboBox<>("Select a planet");

// Add an item with a generated ID
Object itemId = select.addItem();
select.setItemCaption(itemId, "The Sun");

// Select the item
select.setValue(itemId);
// Add items to select
select.setItems("Mercury","Venus","Earth");
----

Some container types may support passing the actual data object to the add
method. For example, you can add items to a [classname]#BeanItemContainer# with
[methodname]#addBean()#. Such implementations can use a separate item ID object,
or the data object itself as the item ID, as is done in [methodname]#addBean()#.
In the latter case you can not depend on the default way of acquiring the item
caption; see the description of the different caption modes later.

The next section describes the different options for determining the item
captions.


[[components.selection.captions]]
== Item Captions

The displayed captions of items in a selection component can be set explicitly
with [methodname]#setItemCaption()# or determined from the item IDs or item
properties. The caption determination is defined with the __caption mode__, any
of the modes in the [classname]#AbstractSelect.ItemCaptionMode# enum, which you
can set with [methodname]#setItemCaptionMode()#. The default mode is
[parameter]#EXPLICIT_DEFAULTS_ID#, which uses the item identifiers for the
captions, unless given explicitly.

In addition to a caption, an item can have an icon. The icon is set with
[methodname]#setItemIcon()#.

The caption modes defined in [classname]#ItemCaptionMode# are the following:

EXPLICIT_DEFAULTS_ID:: This is the default caption mode and its flexibility allows using it in most
cases. By default, the item identifier will be used as the caption. The
identifier object does not necessarily have to be a string; the caption is
retrieved with [methodname]#toString()# method. If the caption is specified
explicitly with [methodname]#setItemCaption()#, it overrides the item
identifier.
The items are typically a strings, in which case they can be used as the
caption, but can be any object type. We could as well have given Planet instances
for the items and use captions generated based on them
[methodname]#setItemCaptionProvider()# method.


+
[source, java]
----
// List of Planet objects
List<Planet> planets = new ArrayList<>();
planets.add(new Planet("Mercury"));
planets.add(new Planet("Venus"));
planets.add(new Planet("Earth"));

// Create a selection component
ComboBox select = new ComboBox("Moons of Mars");
select.setItemCaptionMode(
ItemCaptionMode.EXPLICIT_DEFAULTS_ID);
ComboBox<Planet> select = new ComboBox<>("My Select");

// The given item ID is also used as the caption
select.addItem(new Integer(1));
// Add an items to the ComboBox
select.setItems(planets);

// Set item caption for this item explicitly
select.addItem(2); // same as "new Integer(2)"
select.setItemCaption(2, "Deimos");
select.setItemCaptionProvider(planet -> planet.getName());
// or even select.setItemCaptionProvider(Planet::getName);

// Select the first
select.select(planets.get(0));
----
EXPLICIT:: Captions must be explicitly specified with [methodname]#setItemCaption()#. If
they are not, the caption will be empty. Such items with empty captions will
nevertheless be displayed in the selection component as empty items. If they
have an icon, they will be visible.

ICON_ONLY:: Only icons are shown, captions are hidden.
In addition to a caption, an item can have an icon. The icon is set with
[methodname]#setItemIconProvider()#.

ID:: String representation of the item identifier object is used as caption. This is
useful when the identifier is a string, and also when the identifier is an
complex object that has a string representation. For example:
Typical use cases for captions are:

Using the items as the caption: the caption is
retrieved with [methodname]#toString()# method from the item. This is useful
for simple objects like String or Integers, but also for objects that have
human readable output for [methodname]#toString()# .

+
[source, java]
----
ComboBox select = new ComboBox("Inner Planets");
select.setItemCaptionMode(ItemCaptionMode.ID);
ComboBox<Planet> select = new ComboBox<>("Inner Planets");

// A class that implements toString()
class PlanetId extends Object
implements Serializable {
class Planet implements Serializable {
String planetName;

PlanetId (String name) {
Planet(String name) {
planetName = name;
}

public String toString () {
return "The Planet " + planetName;
}
}

// Use such objects as item identifiers
String planets[] = {"Mercury", "Venus",
"Earth", "Mars"};
for (int i=0; i<planets.length; i++)
select.addItem(new PlanetId(planets[i]));
// Use such objects as items
List<Planet> planets = new ArrayList<>();
planets.add(new Planet("Mercury"));
planets.add(new Planet("Venus"));
planets.add(new Planet("Earth"));

select.addItems(planets);
----

Using a field of a item as caption: the caption is retrieved using the
[interfacename]#ItemCaptionProvider# typically given as Java 8 lambda:



INDEX::
Index number of item is used as caption.
This caption mode is applicable only to data sources that implement the [interfacename]#Container.Indexed# interface.
@@ -238,91 +160,81 @@ a property of the bean as the caption.
+
[source, java]
----
/** A bean with a "name" property. */
public class Planet implements Serializable {
int id;
String name;

public Planet(int id, String name) {
this.id = id;
this.name = name;
// A class that implements toString()
class Planet implements Serializable {
Integer id;
String planetName;

Planet(Integer id, String name) {
this.id = id
this.planetName = name;
}

public String toString () {
return "The Planet " + planetName;
}

public Integer getId () {
return id;
}


public String getName () {
return planetName;
}

... setters and getters ...
}

public void captionproperty(
VerticalLayout layout) {
// Have a bean container to put the beans in
BeanItemContainer<Planet> container =
new BeanItemContainer<Planet>(
Planet.class);

// Put some example data in it
container.addItem(
new Planet(1, "Mercury"));
container.addItem(new Planet(2, "Venus"));
container.addItem(new Planet(3, "Earth"));
container.addItem(new Planet(4, "Mars"));

// Create a selection component bound
// to the container
ComboBox select = new ComboBox("Planets",
container);

// Set the caption mode to read the
// caption directly from the 'name'
// property of the bean
select.setItemCaptionMode(
ItemCaptionMode.PROPERTY);
select.setItemCaptionPropertyId("name");

...
// Put some example data
List<Planet> planets = new ArrayList<>();
planets.add(new Planet(1, "Mercury"));
planets.add(new Planet(2, "Venus"));
planets.add(new Planet(3, "Earth"));
planets.add(new Planet(4, "Mars"));

// Create a selection component
ComboBox<Planet> select = new ComboBox<>("Planets");

// Set the caption provider to read the
// caption directly from the 'name'
// property of the bean
select.setItemCaptionProvider(Planet::getName);
----

[[components.selection.getset]]
== Getting and Setting Selection

A selection component provides the current selection as the property of the
component (with the [classname]#Property# interface). The property value is an
item identifier object that identifies the selected item. You can get the
identifier with [methodname]#getValue()# of the [classname]#Property# interface.
You can get the item with [methodname]#getSelected()# of the
[classname]#Select# interface that returns collection of selected items.
You can select an item with the corresponding [methodname]#select()# method.

You can select an item with the corresponding [methodname]#setValue()# method.
In multiselect mode, the property will be an unmodifiable set of item
identifiers. If no item is selected, the property will be [parameter]#null# in
single selection mode or an empty collection in multiselect mode.
In multiselect mode, the [methodname]#getSelected()# returns an unmodifiable
set of items. If no item is selected, the select will be an empty collection.

The [classname]#ComboBox# and [classname]#NativeSelect# will show empty
selection when no actual item is selected. This is the __null selection item
identifier__. You can set an alternative ID with
[methodname]#setNullSelectionItemId()#. Setting the alternative null ID is
merely a visual text; the [methodname]#getValue()# will still return
[parameter]#null# value if no item is selected, or an empty set in multiselect
mode.
selection when no actual item is selected.


[[components.selection.valuechange]]
== Handling Selection Changes

The item identifier of the currently selected item will be set as the property
of the selection component. You can access it with the [methodname]#getValue()#
method of the [classname]#Property# interface of the component. Also, when
handling selection changes with a [classname]#Property.ValueChangeListener#, the
[classname]#ValueChangeEvent# will have the selected item as the property of the
event, accessible with the [methodname]#getProperty()# method.
You can access currently selected item with the [methodname]#getSelected()# or
[methodname]#getFirstSelected()# method of the component. Also, when
handling selection changes with a
[classname]#SelectionChangeListener#, the
[classname]#SelectionChange# will have the selected items of the event.


[source, java]
----
// Create a selection component with some items
ComboBox select = new ComboBox("My Select");
select.addItems("Io", "Europa", "Ganymedes", "Callisto");
ComboBox<String> select = new ComboBox<>("My Select");
select.setItems("Io", "Europa", "Ganymedes", "Callisto");

// Handle selection change
select.addValueChangeListener(event -> // Java 8
select.addSelectionChangeListener(event ->
layout.addComponent(new Label("Selected " +
event.getProperty().getValue())));
event.getSelected())));
----

The result of user interaction is shown in
@@ -336,146 +248,112 @@ image::img/select-selected1.png[width=30%, scaledwidth=40%]
[[components.selection.newitems]]
== Allowing Adding New Items

Some selection components can allow the user to add new items. Currently, only
[classname]#ComboBox# allows it, when the user types in a value and presses
kbd:[Enter]. You need to enable the mode with [methodname]#setNewItemsAllowed(true)#.
Setting the component also in immediate mode may be necessary, as otherwise the
item would not be added immediately when the user interacts with the component,
but after some other component causes a server
request.
// TODO This could be a bug

[classname]#ComboBox# allows the user to add new items, when the user types
in a value and presses kbd:[Enter]. You need to enable this with
[methodname]#setNewItemHandler()#.

[source, java]
----
myselect.setNewItemsAllowed(true);
myselect.setImmediate(true);
----

The user interface for adding new items depends on the selection component. The
regular [classname]#ComboBox# component allows you to simply type the new item
in the combo box and hit kbd:[Enter] to add it.

Adding new items is not possible if the selection component is read-only or is
bound to a [classname]#Container# that does not allow adding new items. An
Adding new items is not possible if the selection component is read-only. An
attempt to do so may result in an exception.

[[components.selection.newitems.handling]]
=== Handling New Items

Adding new items is handled by a [interfacename]#NewItemHandler#, which gets the
item caption string as parameter for the [methodname]#addNewItem()# method. The
default implementation, [classname]#DefaultNewItemHandler#, checks for read-only
state, adds the item using the entered caption as the item ID, and if the
selection component gets the captions from a property, copies the caption to
that property. It also selects the item. The default implementation may not be
suitable for all container types, in which case you need to define a custom
handler. For example, a [classname]#BeanItemContainer# expects the items to have
the bean object itself as the ID, not a string.
item caption string as parameter for the [methodname]#addNewItem()# method.

ifdef::web[]

[source, java]
----
// Have a bean container to put the beans in
final BeanItemContainer<Planet> container =
new BeanItemContainer<Planet>(Planet.class);
// List of planets
List<Planet> planets = new ArrayList<>();
planets.add(new Planet(1, "Mercury"));
planets.add(new Planet(2, "Venus"));
planets.add(new Planet(3, "Earth"));
planets.add(new Planet(4, "Mars"));

// Put some example data in it
container.addItem(new Planet(1, "Mercury"));
container.addItem(new Planet(2, "Venus"));
container.addItem(new Planet(3, "Earth"));
container.addItem(new Planet(4, "Mars"));

final ComboBox select =
new ComboBox("Select or Add a Planet", container);
select.setNullSelectionAllowed(false);
ComboBox<Planet> select =
new ComboBox<>("Select or Add a Planet");
select.setItems(planets);

// Use the name property for item captions
select.setItemCaptionPropertyId("name");
select.setItemCaptionProvider(Planet::getName);

// Allow adding new items
select.setNewItemsAllowed(true);
select.setImmediate(true);
// Allow adding new items and add
// handling for new items
select.setNewItemHandler(inputString -> {

// Custom handling for new items
select.setNewItemHandler(new NewItemHandler() {
@Override
public void addNewItem(String newItemCaption) {
// Create a new bean - can't set all properties
Planet newPlanet = new Planet(0, newItemCaption);
container.addBean(newPlanet);
// Create a new bean - can't set all properties
Planet newPlanet = new Planet(0, inputString);
planets.add(newPlanet);

// Remember to set the selection to the new item
select.select(newPlanet);
// Update combobox content
select.setItems(planets);

Notification.show("Added new planet called " +
newItemCaption);
}
// Remember to set the selection to the new item
select.select(newPlanet);

Notification.show("Added new planet called " +
inputString);
});
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.select.combobox.newitemhandler[on-line example, window="_blank"].
endif::web[]



[[components.selection.multiple]]
== Multiple Selection

Some selection components, such as [classname]#OptionGroup# and
[classname]#ListSelect# support a multiple selection mode, which you can enable
with [methodname]#setMultiSelect()#. For [classname]#TwinColSelect#, which is
especially intended for multiple selection, it is enabled by default.
with [methodname]#setSelectionMode(SelectionMode.MULTI)#.
For [classname]#TwinColSelect#, which is especially intended for
multiple selection, it is enabled by default.


[source, java]
----
myselect.setMultiSelect(true);
myselect.setSelectionMode(SelectionMode.MULTI);
----

As in single selection mode, the property value of the component indicates the
selection. In multiple selection mode, however, the property value is a
[classname]#Collection# of the item IDs of the currently selected items. You can
get and set the property with the [methodname]#getValue()# and
[methodname]#setValue()# methods as usual.
In multiple selection mode the [interfacename]#Select# value is a
[classname]#Collection# of the items of the currently selected items.
You can get and set the selection with the [methodname]#getSelected()# and
[methodname]#setSelected()# methods as usual.

A change in the selection will trigger a [classname]#ValueChangeEvent#, which
you can handle with a [classname]#Propery.ValueChangeListener#. As usual, you
should use [methodname]#setImmediate(true)# to trigger the event immediately
when the user changes the selection. The following example shows how to handle
selection changes with a listener.
A change in the selection will trigger a [classname]#SelectionChange#, which
you can handle with a [classname]#SelectionChangeListener#. The
following example shows how to handle selection changes with a listener.


[source, java]
----
// A selection component with some items
ListSelect select = new ListSelect("My Selection");
select.addItems("Mercury", "Venus", "Earth",
ListSelect<String> select = new ListSelect<>("My Selection");
select.setItems("Mercury", "Venus", "Earth",
"Mars", "Jupiter", "Saturn", "Uranus", "Neptune");

// Multiple selection mode
select.setMultiSelect(true);
select.setSelectionMode(SelectionMode.MULTI);

// Feedback on value changes
select.addValueChangeListener(
new Property.ValueChangeListener() {
public void valueChange(ValueChangeEvent event) {
select.addSelectionChangeListener(event -> {
// Some feedback
layout.addComponent(new Label("Selected: " +
event.getProperty().getValue().toString()));
event.getSelected()));
}
});
select.setImmediate(true);
----


[[components.selection.item-icons]]
== Item Icons

You can set an icon for each item with [methodname]#setItemIcon()#, or define an
item property that provides the icon resource with
[methodname]#setItemIconPropertyId()#, in a fashion similar to captions. Notice,
however, that icons are not supported in [classname]#NativeSelect#,
[classname]#TwinColSelect#, and some other selection components and modes. This
is because HTML does not support images inside the native [literal]#++select++#
You can set an icon for each item with [methodname]#setItemIconProvider()#,
in a fashion similar to captions. Notice, however, that icons are not
supported in [classname]#NativeSelect#, [classname]#TwinColSelect#, and
some other selection components and modes. This is because HTML does not
support images inside the native [literal]#++select++#
elements. Icons are also not really visually applicable.

読み込み中…
キャンセル
保存