@@ -27,8 +27,8 @@ The _widget set_ needs to be compiled into the application widget set. | |||
Adding the dependency in Maven projects and compiling the widget set is described in <<addons-maven#addons.maven, "Using Add-ons in a Maven Project">>. | |||
The section also describes how to use the online compilation and CDN services during development. | |||
For Eclipse projects that use Ivy for dependency management, see <<addons-eclipse#addons.eclipse, "Installing Add-ons in Eclipse with Ivy">>. | |||
You can also download and install add-ons from a ZIP-package, as described in <<addons-downloading#addons.downloading, "Downloading Add-ons from Vaadin Directory">>. | |||
For Eclipse projects that use Ivy for dependency management, see <<dummy/../../../framework/addons/addons-eclipse.asciidoc#addons.eclipse, "Installing Add-ons in Eclipse with Ivy">>. | |||
You can also download and install add-ons from a ZIP-package, as described in <<dummy/../../../framework/addons/addons-downloading.asciidoc#addons.downloading, "Downloading Add-ons from Vaadin Directory">>. | |||
== Add-on Licenses | |||
@@ -235,10 +235,6 @@ one returns a UI (otherwise they return null). You can add a UI provider to a | |||
session most conveniently by implementing a custom servlet and adding the UI | |||
provider to sessions in a [interfacename]#SessionInitListener#. | |||
You can find an example of custom UI providers in | |||
<<dummy/../../../mobile/mobile-features#mobile.features.fallback,"Providing a | |||
Fallback UI">>. | |||
[[application.lifecycle.ui.preserving]] | |||
=== Preserving UI on Refresh |
@@ -45,8 +45,6 @@ The result is shown in <<figure.components.checkbox.basic>>. | |||
.An Example of a Check Box | |||
image::img/checkbox-example1.png[width=35%, scaledwidth=50%] | |||
For an example on the use of check boxes in a table, see | |||
<<dummy/../../../framework/components/components-table#components.table,"Table">>. | |||
== CSS Style Rules | |||
@@ -24,12 +24,6 @@ Components">>. | |||
.The [classname]#ComboBox# Component | |||
image::img/combobox-basic.png[width=35%, scaledwidth=50%] | |||
[classname]#ComboBox# supports adding new items when the user presses | |||
kbd:[Enter]. | |||
ifdef::web[] | |||
See <<dummy/../../../framework/components/components-selection#components.selection.newitems,"Allowing Adding New Items">>. | |||
endif::web[] | |||
[[components.combobox.filtering]] | |||
== Filtered Selection | |||
@@ -73,6 +67,57 @@ containing the input string. As shown in <<figure.components.combobox.filter>> | |||
below, when we type some text in the input area, the drop-down list will show | |||
all the matching items. | |||
[[components.combobox.newitems]] | |||
== Allowing Adding New Items | |||
[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()#. | |||
Adding new items is not possible if the selection component is read-only. An | |||
attempt to do so may result in an exception. | |||
=== Handling New Items | |||
Adding new items is handled by a [interfacename]#NewItemHandler#, which gets the | |||
item caption string as parameter for the [methodname]#accept(String)# method. | |||
[source, java] | |||
---- | |||
// 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")); | |||
ComboBox<Planet> select = | |||
new ComboBox<>("Select or Add a Planet"); | |||
select.setItems(planets); | |||
// Use the name property for item captions | |||
select.setItemCaptionGenerator(Planet::getName); | |||
// Allow adding new items and add | |||
// handling for new items | |||
select.setNewItemHandler(inputString -> { | |||
// Create a new bean - can't set all properties | |||
Planet newPlanet = new Planet(planets.size(), inputString); | |||
planets.add(newPlanet); | |||
// Update combobox content | |||
select.setItems(planets); | |||
// Remember to set the selection to the new item | |||
select.select(newPlanet); | |||
Notification.show("Added new planet called " + | |||
inputString); | |||
}); | |||
---- | |||
[[components.combobox.css]] | |||
== CSS Style Rules |
@@ -8,7 +8,7 @@ layout: page | |||
= Composite Fields with [classname]#CustomField# | |||
The [classname]#CustomField# is a way to create composite components as with [classname]#CustomComponent#, except that it implements the [interfacename]#Field# interface and inherits [classname]#AbstractField#, described in <<dummy/../../../framework/components/components-fields#components.fields,"Field Components">>. | |||
A field allows editing a property value in the Vaadin data model, and can be bound to data with field groups, as described in <<dummy/../../../framework/datamodel/datamodel-itembinding#datamodel.itembinding, "Creating Forms by Binding Fields to Items">>. | |||
A field allows editing a property value in the Vaadin data model, and can be bound to data with field groups, as described in <<dummy/../../../framework/datamodel/datamodel-forms#datamodel.forms, "Binding Data to Forms">>. | |||
The field values are buffered and can be validated with validators. | |||
A composite field class must implement the [methodname]#getType()# and [methodname]#initContent()# methods. |
@@ -70,7 +70,6 @@ around a component. | |||
---- | |||
.v-caption {} | |||
.v-captiontext {} | |||
.v-caption-clearelem {} | |||
.v-required-field-indicator {} | |||
---- | |||
@@ -78,10 +77,8 @@ A caption is be rendered inside an HTML element that has the | |||
[literal]#++v-caption++# CSS style class. The containing layout may enclose a | |||
caption inside other caption-related elements. | |||
Some layouts put the caption text in a [literal]#++v-captiontext++# element. A | |||
[literal]#++v-caption-clearelem++# is used in some layouts to clear a CSS | |||
[literal]#++float++# property in captions. An optional required indicator in | |||
field components is contained in a separate element with | |||
Some layouts put the caption text in a [literal]#++v-captiontext++# element. | |||
An optional required indicator in field components is contained in a separate element with | |||
[literal]#++v-required-field-indicator++# style. | |||
@@ -143,9 +140,6 @@ The result is shown in <<figure.components.tooltip.richtext>>. | |||
.A Rich Text Tooltip | |||
image::img/tooltip-richtext-withpointer-hi.png[width=40%, scaledwidth=75%] | |||
Notice that the setter and getter are defined for all field components implementing the | |||
[classname]#HasValue# interface, not for all components. | |||
[[components.features.enabled]] | |||
== Enabled | |||
@@ -182,10 +176,8 @@ A disabled component is automatically put in read-only like state. No client | |||
interaction with a disabled component is sent to the server and, as an important | |||
security feature, the server-side components do not receive state updates from | |||
the client in the disabled state. This feature exists in all built-in | |||
components in Vaadin and is automatically handled for all [classname]#HasValue# | |||
components that have a value. For custom widgets, you need to make | |||
sure that the disabled state is checked on the server-side for all | |||
safety-critical variables. | |||
components in the Framework meaning all client to server RPC calls are ignored | |||
for disabled components. | |||
=== CSS Style Rules | |||
@@ -203,11 +195,8 @@ have to join the style class names with a dot as done in the example below. | |||
This would make the border of all disabled text fields dotted. | |||
// TODO This may change to $v-button-disabled-opacity | |||
In the Valo theme, the opacity of disabled components is specified with the | |||
`$v-disabled-opacity` | |||
ifndef::web[parameter.] | |||
ifdef::web[parameter, as described in <<dummy/../../../framework/themes/themes-valo#themes.valo.variables,"Common Settings">>] | |||
`$v-disabled-opacity` parameter. | |||
[[components.features.icon]] | |||
== Icon | |||
@@ -294,7 +283,6 @@ date.setLocale(new Locale("de", "DE")); | |||
date.setResolution(Resolution.DAY); | |||
layout.addComponent(date); | |||
---- | |||
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.features.locale.simple[on-line example, window="_blank"]. | |||
The resulting date field is shown in <<figure.components.features.locale.simple>>. | |||
@@ -302,7 +290,7 @@ The resulting date field is shown in <<figure.components.features.locale.simple> | |||
.Set locale for [classname]#InlineDateField# | |||
image::img/features-locale-simple.png[width=40%, scaledwidth=60%] | |||
ifdef::web[] | |||
[[components.features.locale.get]] | |||
=== Getting the Locale | |||
@@ -331,7 +319,6 @@ Button cancel = new Button() { | |||
}; | |||
layout.addComponent(cancel); | |||
---- | |||
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.features.locale.get-attach[on-line example, window="_blank"]. | |||
However, it is normally a better practice to use the locale of the current UI to | |||
get the localized resource right when the component is created. | |||
@@ -349,73 +336,17 @@ Button cancel = | |||
new Button(bundle.getString(MyAppCaptions.CancelKey)); | |||
layout.addComponent(cancel); | |||
---- | |||
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.features.locale.get-ui[on-line example, window="_blank"]. | |||
endif::web[] | |||
ifdef::web[] | |||
[[component.features.locale.selecting]] | |||
=== Selecting a Locale | |||
A common task in many applications is selecting a locale. This is done in the | |||
following example with a [classname]#ComboBox#, which gets the available locales | |||
in Java. | |||
[source, java] | |||
---- | |||
// The locale in which we want to have the language | |||
// selection list | |||
Locale displayLocale = Locale.ENGLISH; | |||
// All known locales | |||
final Locale[] locales = Locale.getAvailableLocales(); | |||
// Allow selecting a language. We are in a constructor of a | |||
// CustomComponent, so preselecting the current | |||
// language of the application can not be done before | |||
// this (and the selection) component are attached to | |||
// the application. | |||
ComboBox<Locale> select = new ComboBox<>("Select a language") { | |||
@Override | |||
public void attach() { | |||
super.attach(); | |||
setValue(getLocale()); | |||
} | |||
}; | |||
select.setItems(Arrays.asList(locales)); | |||
select.setCaptionGenerator(locale -> locale.getDisplayName(displayLocale)); | |||
select.setValue(getLocale()); | |||
layout.addComponent(select); | |||
// Locale code of the selected locale | |||
Label localeCode = new Label(""); | |||
layout.addComponent(localeCode); | |||
// A date field which language the selection will change | |||
InlineDateField date = | |||
new InlineDateField("Calendar in the selected language"); | |||
date.setResolution(Resolution.DAY); | |||
layout.addComponent(date); | |||
// Handle language selection | |||
select.onValueChange(locale -> { | |||
date.setLocale(locale); | |||
localeCode.setValue("Locale code: " + | |||
locale.getLanguage() + "_" + | |||
locale.getCountry()); | |||
}); | |||
---- | |||
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.features.locale.selection[on-line example, window="_blank"]. | |||
The user interface is shown in <<figure.components.features.locale.selection>>. | |||
[[figure.components.features.locale.selection]] | |||
.Selecting a locale | |||
image::img/features-locale-selection.png[] | |||
endif::web[] | |||
A common task in many applications is selecting a locale. | |||
The locale can be set for the [classname]#UI# or single [classname]#Component#. | |||
By default each component uses the locale from the [classname]#UI# it has been | |||
attached to. Setting a locale to a [classname]#Component# only applies the locale | |||
to that component and its children. Note, that updating the locale for a component | |||
does not update its children, thus any child component that uses the locale should be updated manually. | |||
[[components.features.readonly]] | |||
@@ -424,20 +355,17 @@ endif::web[] | |||
((("read-only property"))) | |||
((("Component interface", "read-only"))) | |||
The property defines whether the value of a component can be changed. The | |||
property is only applicable to [classname]#HasValue# components implementing the `HasValue` interface, as they have a | |||
value that can be edited by the user. | |||
property is only applicable to components implementing the [interfacename]#HasValue# interface. | |||
[source, java] | |||
---- | |||
TextField readwrite = new TextField("Read-Write"); | |||
readwrite.setValue("You can change this"); | |||
readwrite.setReadOnly(false); // The default | |||
layout.addComponent(readwrite); | |||
TextField readonly = new TextField("Read-Only"); | |||
readonly.setValue("You can't touch this!"); | |||
readonly.setReadOnly(true); | |||
layout.addComponent(readonly); | |||
---- | |||
The resulting read-only text field is shown in | |||
@@ -467,10 +395,6 @@ and some of such changes could be acceptable, such as change in the scroll bar | |||
position of a [classname]#ListSelect#. Custom components should check the read-only | |||
state for variables bound to business data. | |||
//// | |||
TODO: Note this also in the Advanced: Security section. | |||
Possibly also in the GWT chapter. | |||
//// | |||
=== CSS Style Rules | |||
@@ -562,13 +486,6 @@ invisible.setVisible(false); | |||
layout.addComponent(invisible); | |||
---- | |||
The resulting invisible component is shown in | |||
<<figure.components.features.visible.simple>>. | |||
[[figure.components.features.visible.simple]] | |||
.An invisible component | |||
image::img/features-visible-simple.png[] | |||
If you need to make a component only cosmetically invisible, you should use a | |||
custom theme to set it [literal]#++display: none++# style. This is mainly useful | |||
for some special components that have effects even when made invisible in CSS. | |||
@@ -579,10 +496,6 @@ invisible by setting all its font and other attributes to be transparent. In | |||
such cases, the invisible content of the component can be made visible easily in | |||
the browser. | |||
A component made invisible with the __visible__ property has no particular CSS | |||
style class to indicate that it is hidden. The element does exist though, but | |||
has [literal]#++display: none++# style, which overrides any CSS styling. | |||
[[components.features.sizeable]] | |||
== Sizing Components | |||
@@ -601,9 +514,6 @@ The size of a component can be set with [methodname]#setWidth()# and | |||
[methodname]#setHeight()# methods. The methods take the size as a floating-point | |||
value. You need to give the unit of the measure as the second parameter for the | |||
above methods. | |||
ifdef::web[] | |||
The available units are listed in <<components.features.sizeable.units.table>>. | |||
endif::web[] | |||
[source, java] | |||
---- | |||
@@ -622,8 +532,7 @@ mycomponent.setHeight("400px"); | |||
---- | |||
The "[literal]#++100%++#" percentage value makes the component take all | |||
available size in the particular direction (see the description of | |||
[parameter]#Unit.PERCENTAGE# in the table below). You can also use the | |||
available size in the particular direction. You can also use the | |||
shorthand method [methodname]#setSizeFull()# to set the size to 100% in both | |||
directions. | |||
@@ -631,31 +540,11 @@ The size can be __undefined__ in either or both dimensions, which means that the | |||
component will take the minimum necessary space. Most components have undefined | |||
size by default, but some layouts have full size in horizontal direction. You | |||
can set the height, width, or both as undefined with the methods [methodname]#setWidthUndefined()#, | |||
[methodname]#setHeightUndefined()#, and [methodname]#setHeightUndefined()#, respectively. | |||
[methodname]#setHeightUndefined()#, and [methodname]#setSizeUndefined()#, respectively. | |||
Always keep in mind that _a layout with undefined size may not contain components with defined relative size_, such as "full size", except in some special cases. | |||
See <<dummy/../../../framework/layout/layout-settings#layout.settings.size,"Layout Size">> for details. | |||
ifdef::web[] | |||
The <<components.features.sizeable.units.table>> table lists the available units and their codes defined in the [interfacename]#Sizeable# interface. | |||
[[components.features.sizeable.units.table]] | |||
.Size units | |||
[cols="5,2,10", options="header"] | |||
|=============== | |||
|Constant|Unit|Description | |||
|[parameter]#Unit.PIXELS#|px|The _pixel_ is the basic hardware-specific measure of one physical display pixel. | |||
|[parameter]#Unit.POINTS#|pt|The _point_ is a typographical unit, which is usually defined as 1/72 inches or about 0.35 mm. However, on displays the size can vary significantly depending on display metrics. | |||
|[parameter]#Unit.PICAS#|pc|The _pica_ is a typographical unit, defined as 12 points, or 1/7 inches or about 4.233 mm. On displays, the size can vary depending on display metrics. | |||
|[parameter]#Unit.EM#|em|A unit relative to the used font, the width of the upper-case "M" letter. | |||
|[parameter]#Unit.EX#|ex|A unit relative to the used font, the height of the lower-case "x" letter. | |||
|[parameter]#Unit.MM#|mm|A physical length unit, millimeters on the surface of a display device. However, the actual size depends on the display, its metrics in the operating system, and the browser. | |||
|[parameter]#Unit.CM#|cm|A physical length unit, _centimeters_ on the surface of a display device. However, the actual size depends on the display, its metrics in the operating system, and the browser. | |||
|[parameter]#Unit.INCH#|in|A physical length unit, _inches_ on the surface of a display device. However, the actual size depends on the display, its metrics in the operating system, and the browser. | |||
|[parameter]#Unit.PERCENTAGE#|%|A relative percentage of the available size. For example, for the top-level layout [parameter]#100%# would be the full width or height of the browser window. The percentage value must be between 0 and 100. | |||
|=============== | |||
endif::web[] | |||
If a component inside [classname]#HorizontalLayout# or [classname]#VerticalLayout# has full size in the namesake direction of the layout, the component will expand to take all available space not needed by the other components. | |||
See <<dummy/../../../framework/layout/layout-settings#layout.settings.size,"Layout Size">> for details. | |||
@@ -19,59 +19,54 @@ and the important interfaces and base classes. | |||
.Field components | |||
image::img/field-diagram-hi.png[width=80%, scaledwidth=100%] | |||
Field components are built upon the framework defined in the [classname]#Field# | |||
interface and the [classname]#AbstractField# base class. | |||
[classname]#AbstractField# is the base class for all field components. In | |||
addition to the component features inherited from | |||
Field components are built upon the framework defined in the [classname]#HasValue# | |||
interface. | |||
[classname]#AbstractField# is the base class for all field components, | |||
except those components that allow the user to select a value. | |||
(see <<dummy/../../../framework/components/components-selection.asciidoc#components.selection,"Selection Components">>). | |||
In addition to the component features inherited from | |||
[classname]#AbstractComponent#, it implements the features defined in the | |||
[classname]#HasValue# and [classname]#Component.Focusable# interfaces. | |||
[interfacename]#HasValue# and [classname]#Component.Focusable# interfaces. | |||
[[figure.components.fields.hasvalue]] | |||
.Field components having values | |||
image::img/field-interface-v8-hi.png[width=60%, scaledwidth=100%] | |||
The description of the field interfaces and base classes is broken down in the | |||
following sections. | |||
The description of the [interfacename]#HasValue# interface and field components extending [classname]#AbstractField] is broken down in the following sections. | |||
[[components.fields.field]] | |||
== The [classname]#Field# Interface | |||
The [classname]#Field# interface inherits the [classname]#Component# | |||
superinterface and also the [classname]#HasValue# interface to have a value for | |||
the field. [classname]#AbstractField# is the only class implementing the | |||
[classname]#Field# interface directly. The relationships are illustrated in | |||
<<figure.components.fields.field>>. | |||
== The [interfacename]#HasValue# Interface | |||
[[figure.components.fields.field]] | |||
.[classname]#Field# interface inheritance | |||
image::img/field-interface-hi.png[width=60%, scaledwidth=100%] | |||
The [interfacename]#HasValue# interface marks a component that has a user editable value. | |||
The type parameter in the interface is the type of the value that the component is editing. | |||
You can set the field value with the [methodname]#setValue()# and read with the | |||
You can set the value with the [methodname]#setValue()# and read it with the | |||
[methodname]#getValue()# method defined in the [classname]#HasValue# interface. | |||
The actual value type depends on the component. | |||
The [classname]#Field# interface defines a number of properties, which you can | |||
The [classname]#HasValue# interface defines a number of properties, which you can | |||
access with the corresponding setters and getters. | |||
[methodname]#required#:: When enabled, a required indicator (usually the asterisk * character) is | |||
displayed on the left, above, or right the field, depending on the containing | |||
layout and whether the field has a caption. If such fields are validated but are | |||
empty and the [methodname]#requiredError# property (see below) is set, an error | |||
indicator is shown and the component error is set to the text defined with the | |||
error property. Without validation, the required indicator is merely a visual | |||
guide. | |||
[methodname]#requiredError#:: Defines the error message to show when a value is required, but none is entered. | |||
The error message is set as the component error for the field and is usually | |||
displayed in a tooltip when the mouse pointer hovers over the error indicator. | |||
[methodname]#readOnly#:: Set the component to be read-only, meaning that the value is not editable. | |||
[[components.fields.valuechanges]] | |||
== Handling Field Value Changes | |||
[methodname]#requiredIndicatorVisible#:: When enabled, a required indicator | |||
(the asterisk * character) is displayed on the left, above, or right the field, | |||
depending on the containing layout and whether the field has a caption. | |||
When the component is used in a form (see <<dummy/../../../framework/datamodel/datamodel-forms.asciidoc#datamodel.forms.validation,"Validation">>), | |||
it can be set to be required, which will automatically show the required indicator, | |||
and validate that the value is not empty. Without validation, the required indicator | |||
is merely a visual guide. | |||
[methodname]#emptyValue#:: The initial empty value of the component. | |||
[methodname]#clear#:: Clears the value to the empty value. | |||
[classname]#Field# provides [methodname]#addValueChangeListener# method for listening to changes to the field value. This method takes a [interfacename]#EventListener# that gets | |||
a [classname]#ValueChange# event instance containing information about the event. | |||
This method returns a [classname]#Registration# object that can be used to later | |||
[[components.fields.valuechanges]] | |||
== Handling Value Changes | |||
[interfacename]#HasValue# provides [methodname]#addValueChangeListener# method for listening to changes to the field value. This method returns a [classname]#Registration# object that can be used to later | |||
remove the added listener if necessary. | |||
[source, java] | |||
@@ -79,7 +74,6 @@ remove the added listener if necessary. | |||
TextField textField = new TextField(); | |||
Label echo = new Label(); | |||
// Add a more complex listener | |||
textField.addValueChangeListener(event -> { | |||
String origin = event.isUserOriginated() | |||
? "user" | |||
@@ -91,6 +85,7 @@ textField.addValueChangeListener(event -> { | |||
}); | |||
---- | |||
[[components.fields.databinding]] | |||
== Binding Fields to Data | |||
@@ -114,16 +109,18 @@ Binder<Person> binder = new Binder<>(); | |||
// Bind nameField to the Person.name property | |||
// by specifying its getter and setter | |||
binder.forField(nameField) | |||
.bind(Person::getName, Person::setName); | |||
binder.bind(nameField, Person::getName, Person::setName); | |||
// Bind an actual concrete Person instance. | |||
// After this, whenever the user changes the value | |||
// of nameField, p.setName is automatically called. | |||
Person p = new Person(); | |||
binder.bind(p; | |||
binder.bind(p); | |||
---- | |||
For more information on data binding, see <<dummy/../../../framework/datamodel/datamodel-forms.asciidoc#datamodel.forms,"Binding Data to Forms">> | |||
== Validating Field Values | |||
User input may be syntactically or semantically invalid. | |||
@@ -131,40 +128,24 @@ User input may be syntactically or semantically invalid. | |||
automatically checking the validity of the input before storing it to the data | |||
object. You can add validators to fields by calling the [methodname]#withValidator# | |||
method on the [interfacename]#Binding# object returned by [methodname]#Binder.forField#. | |||
There are several built-in validators in the Framework, such as the [classname]#StringLengthValidator# used below. | |||
[source, java] | |||
---- | |||
binder.forField(nameField) | |||
.withValidator(new StringLengthValidator(2, 20, | |||
"Name must be between 2 and 20 characters long")) | |||
.withValidator(new StringLengthValidator( | |||
"Name must be between 2 and 20 characters long", | |||
2, 20)) | |||
.bind(Person::getName, Person::setName); | |||
---- | |||
Failed validation is indicated with the error indicator of the field, described in | |||
Failed validation is by default indicated with the error indicator of the field, described in | |||
<<dummy/../../../framework/application/application-errors#application.errors.error-indicator,"Error | |||
Indicator and Message">>. Hovering mouse on the field displays the error message | |||
returned by the validator. If any value in a set of bound fields fails validation, | |||
none of the field values are saved into the bound property until the validation | |||
passes. | |||
[[components.fields.validation.builtin]] | |||
=== Built-in Validators | |||
Vaadin includes the following built-in validators. The property value type is | |||
indicated. | |||
[classname]#RangeValidator#: [classname]#Comparable#:: | |||
Checks that the given [interfacename]#Comparable# value is at or between two given values. | |||
[classname]#StringLengthValidator#: [classname]#String#:: | |||
Checks that the length of the input string is at or between two given lengths. | |||
[classname]#RegexpValidator#: [classname]#String#:: | |||
Checks that the value matches the given regular expression. | |||
[classname]#EmailValidator#: [classname]#String#:: | |||
Checks that the string value is a syntactically valid email address. | |||
The validated syntax is close to the RFC 822 standard regarding email addresses. | |||
=== Implementing Custom Validators | |||
@@ -177,7 +158,7 @@ whether or not the given input was valid. | |||
---- | |||
class MyValidator implements Validator<String> { | |||
@Override | |||
public Result<String> apply(String input) { | |||
public Result<String> apply(String value, ValueContext context) { | |||
if(input.length() == 6) { | |||
return Result.ok(input); | |||
} else { | |||
@@ -211,8 +192,7 @@ Field values are always of some particular type. For example, | |||
a data source, the type of the source property can be something different, | |||
say an [classname]#Integer#. __Converters__ are used for converting the values | |||
between the presentation and the model. Their usage is described in | |||
<<dummy/../../../framework/datamodel/datamodel-properties#datamodel.properties.converter,"Converting | |||
Between Model and Presentation Types">>. | |||
<<dummy/../../../framework/datamodel/datamodel-forms.asciidoc#datamodel.forms.conversion,"Conversion">>. | |||
(((range="endofrange", startref="term.components.fields"))) |
@@ -924,8 +924,7 @@ grid.setEditorBinder(binder); | |||
To use bean validation as in the example above, you need to include an | |||
implementation of the Bean Validation API in the classpath, as described in | |||
<<dummy/../../../framework/datamodel/datamodel-itembinding#datamodel.itembinding.beanvalidation,"Bean | |||
Validation">>. | |||
<<dummy/../../../framework/datamodel/datamodel-forms.asciidoc#datamodel.forms.beans,"Binding Beans to Forms">>. | |||
ifdef::web[] |
@@ -92,15 +92,8 @@ described in <<components.interfaces.abstractcomponent>>. | |||
[classname]#AbstractComponent# is the base class for all user interface | |||
components. It is the (only) implementation of the [classname]#Component# | |||
interface, implementing all the methods defined in the interface. | |||
[classname]#AbstractComponent# has a single abstract method, | |||
[methodname]#getTag()#, which returns the serialization identifier of a | |||
particular component class. It needs to be implemented when (and only when) | |||
creating entirely new components. [classname]#AbstractComponent# manages much of | |||
the serialization of component states between the client and the server. | |||
Creation of new components and serialization is described in | |||
<<dummy/../../../framework/gwt/gwt-overview.asciidoc#gwt.overview,"Integrating | |||
with the Server-Side">>. | |||
interface, implementing all the methods defined in the interface. When | |||
creating a new component, you should extend [classname]#AbstractComponent# or | |||
one of its subclasses. | |||
(((range="endofrange", startref="term.components.interfaces.abstractcomponent"))) |
@@ -72,7 +72,7 @@ panel.setContent( | |||
As the size of the [classname]#Panel# in the above example is fixed and the | |||
width of [classname]#Label# is the default undefined, the [classname]#Label# | |||
will overflow the layout horizontally and be truncated. | |||
<<figure.components.label>>. | |||
//<<figure.components.label>>. | |||
//// | |||
// TODO update figure to match new label settings in Vaadin Framwork 8 |
@@ -11,9 +11,7 @@ For a better overview on how selection works, see link:../datamodel/datamodel-se | |||
Vaadin offers many alternative ways for selecting one or more items. The core | |||
library includes the following selection components, all based on either | |||
`AbstractSingleSelect` or `AbstractMultiSelect` class: | |||
// TODO Only use section numbers here, prefixed with "Section", not include section title | |||
[classname]#AbstractSingleSelect# or [classname]#AbstractMultiSelect# class: | |||
[classname]#ComboBox# (<<components-combobox#components.combobox,"ComboBox">>):: | |||
A drop-down list with a text box, where the user can type text to find matching items. | |||
@@ -74,13 +72,12 @@ ComboBox<Planet> select = new ComboBox<>("My Select"); | |||
// Add an items to the ComboBox | |||
select.setItems(planets); | |||
select.setItemCaptionGenerator(planet -> planet.getName()); | |||
// or even select.setItemCaptionGenerator(Planet::getName); | |||
select.setItemCaptionGenerator(Planet::getName); | |||
// Select the first | |||
select.setSelectedItem(planets.get(0)); | |||
// or | |||
select.setValue(planets.get(0)); | |||
// select.setValue(planets.get(0)); | |||
---- | |||
In addition to a caption, an item can have an icon. The icon is set with | |||
@@ -93,78 +90,8 @@ 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<Planet> select = new ComboBox<>("Inner Planets"); | |||
// A class that implements toString() | |||
class Planet implements Serializable { | |||
String planetName; | |||
Planet(String name) { | |||
planetName = name; | |||
} | |||
public String toString () { | |||
return "The Planet " + planetName; | |||
} | |||
} | |||
// 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.setItems(planets); | |||
---- | |||
Using a field of a item as caption: the caption is retrieved using the | |||
[interfacename]#ItemCaptionGenerator# typically given as Java 8 lambda. | |||
[source, java] | |||
---- | |||
// 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; | |||
} | |||
} | |||
// 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 generator to read the | |||
// caption directly from the 'name' | |||
// property of the bean | |||
select.setItemCaptionGenerator(Planet::getName); | |||
---- | |||
[interfacename]#ItemCaptionGenerator# typically given as a lambda or a method reference. | |||
[[components.selection.item-icons]] | |||
@@ -178,67 +105,14 @@ support images inside the native [literal]#++select++# | |||
elements. | |||
[[components.selection.newitems]] | |||
== Allowing Adding New Items | |||
[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()#. | |||
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]#accept(String)# method. | |||
ifdef::web[] | |||
[source, java] | |||
---- | |||
// 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")); | |||
ComboBox<Planet> select = | |||
new ComboBox<>("Select or Add a Planet"); | |||
select.setItems(planets); | |||
// Use the name property for item captions | |||
select.setItemCaptionGenerator(Planet::getName); | |||
// Allow adding new items and add | |||
// handling for new items | |||
select.setNewItemHandler(inputString -> { | |||
// Create a new bean - can't set all properties | |||
Planet newPlanet = new Planet(0, inputString); | |||
planets.add(newPlanet); | |||
// Update combobox content | |||
select.setItems(planets); | |||
// Remember to set the selection to the new item | |||
select.select(newPlanet); | |||
Notification.show("Added new planet called " + | |||
inputString); | |||
}); | |||
[[components.selection.getset]] | |||
== Getting and Setting Selection | |||
For a better overview on how selection works, see link:../datamodel/datamodel-selection.asciidoc[Selecting items] | |||
You can get selected the item with [methodname]#getValue()# of the | |||
[classname]#HasValue# interface that returns either a single selected item | |||
(case of `SingleSelect`) or a collection of selected items (case of `MultiSelect`). | |||
[interfacename]#HasValue# interface that returns either a single selected item | |||
(case of [interfacename]#SingleSelect#) or a collection of selected items (case of [interfacename]#MultiSelect#). | |||
You can select an item with the corresponding [methodname]#setValue()# method. | |||
The [classname]#ComboBox# and [classname]#NativeSelect# will show empty | |||
@@ -246,14 +120,14 @@ selection when no actual item is selected. | |||
[[components.selection.valuechange]] | |||
== Handling Selection Changes | |||
== Handling Selection Events | |||
You can access the currently selected item with the [methodname]#getValue()# (`SingleSelect`) or | |||
[methodname]#getSelectedItems()# (`MultiSelect`) method of the component. Also, when | |||
handling selection changes with a | |||
You can access the currently selected item with the [methodname]#getValue()# ([interfacename]#SingleSelect#) or | |||
[methodname]#getSelectedItems()# ([interfacename]#MultiSelect#) method of the component. Also, when | |||
handling selection events with a | |||
[classname]#SelectionListener#, the | |||
[classname]#SelectionEvent# will have the selected items of the event. Single- and Multiselect | |||
components have their own more specific listener and event types, `SingleSelectionListener` for `SingleSelectionEvent` and `MultiSelectionListener` for `MultiSelectionEvent` respectively. Both can be added with the `addSelectionListener` method. | |||
components have their own more specific listener and event types, [interfacename]#SingleSelectionListener# for [classname]#SingleSelectionEvent# and [interfacename]#MultiSelectionListener# for [classname]#MultiSelectionEvent# respectively. Both can be added with the [methodname]#addSelectionListener# method. | |||
[source, java] | |||
@@ -262,7 +136,7 @@ components have their own more specific listener and event types, `SingleSelecti | |||
ComboBox<String> select = new ComboBox<>("My Select"); | |||
select.setItems("Io", "Europa", "Ganymedes", "Callisto"); | |||
// Handle selection change | |||
// Handle selection event | |||
select.addSelectionListener(event -> | |||
layout.addComponent(new Label("Selected " + | |||
event.getSelectedItem().orElse("none"))); | |||
@@ -276,10 +150,6 @@ The result of user interaction is shown in | |||
image::img/select-selected1.png[width=30%, scaledwidth=40%] | |||
---- | |||
endif::web[] | |||
[[components.selection.multiple]] | |||
== Multiple Selection | |||
@@ -290,12 +160,12 @@ Some selection components, such as [classname]#CheckBoxGroup#, | |||
they extend [classname]#AbstractMultiSelect# class. | |||
Multiselect components use the `MultiSelect` interface which extends `HasValue`. | |||
This provides more fine grained API for selection. You can get and set the selection with the [methodname]#MultiSelect.getSelectedItems()# and | |||
[methodname]#SelectionModel.Multi.selectItems()# methods. | |||
Multiselect components use the [interfacename]#MultiSelect# interface which extends [interfacename]#HasValue#. | |||
This provides more fine grained API for selection. You can get and set the selection with the [methodname]#getSelectedItems()# and | |||
[methodname]#select()# methods. | |||
A change in the selection will trigger a [classname]#SelectionChange#, which | |||
you can handle with a [classname]#SelectionChangeListener#. The | |||
A change in the selection will trigger a [classname]#SelectionEvent#, which | |||
you can handle with a [classname]#SelectionListener#. The | |||
following example shows how to handle selection changes with a listener. | |||
@@ -49,8 +49,7 @@ See the http://demo.vaadin.com/book-examples-vaadin7/book#component.textfield.in | |||
[classname]#TextField# edits [classname]#String# values, but you can use [classname]#Binder# | |||
to bind it to any property type that has a proper converter, as described in | |||
<<dummy/../../../framework/datamodel/datamodel-properties#datamodel.properties.converter,"Converting | |||
Between Property Type and Representation">>. | |||
<<dummy/../../../framework/datamodel/datamodel-forms.asciidoc#datamodel.forms.conversion,"Conversion">>. | |||
Much of the API of [classname]#TextField# is defined in | |||
[classname]#AbstractTextField#, which allows different kinds of text input |
@@ -97,6 +97,7 @@ binder.bind(nameField, | |||
`Binder` supports checking the validity of the user's input and converting the values between the type used in business objects and the bound UI components. | |||
These to concepts go hand in hand since validation can be based on a converted value, and being able to convert a value is a kind of validation. | |||
[[datamodel.forms.validation]] | |||
=== Validation | |||
An application typically has some restrictions on exactly what kinds of values the user is allowed to enter into different fields. | |||
@@ -198,6 +199,7 @@ returnBinding.bind(Trip::getReturnDate, Trip::setReturnDate); | |||
departing.addValueChangeListener(event -> returnBinding.validate()); | |||
---- | |||
[[datamodel.forms.conversion]] | |||
=== Conversion | |||
You can also bind application data to a UI field component even though the types do not match. | |||
@@ -411,6 +413,7 @@ Button saveButton = new Button("Save", event -> { | |||
When using the `setBean` method, the business object instance will be updated whenever the user changes the value in any bound field. | |||
If some other part of the application is also using the same instance, then that part might show changes before the user has clicked the save button. | |||
[[datamodel.forms.beans]] | |||
== Binding Beans to Forms | |||
The business objects used in an application are in most cases implemented as Java beans or POJOs. |