1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
|
---
title: Field Components
order: 4
layout: page
---
[[components.fields]]
= Field Components
((("[classname]#Field#", id="term.components.fields", range="startofrange")))
_Fields_ are components that have a value that the user can change through the
user interface.
<<figure.components.fields>> illustrates the inheritance relationships and the important interfaces and base classes.
[[figure.components.fields]]
.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
[classname]#AbstractComponent#, it implements a number of features defined in
[classname]#Property#, [classname]#Buffered#, [classname]#Validatable#, and
[classname]#Component.Focusable# interfaces.
The description of the field interfaces and base classes is broken down in the
following sections.
[[figure.components.fields.hasvalue]]
.Field components having values
image::img/field-interface-v8-hi.png[width=60%, scaledwidth=100%]
[[components.fields.field]]
== The [classname]#Field# Interface
The [classname]#Field# interface inherits the [classname]#Component#
superinterface and also the [classname]#Property# 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>>.
[[figure.components.fields.field]]
.[classname]#Field# interface inheritance
image::img/field-interface-hi.png[width=60%, scaledwidth=100%]
You can set the field value with the [methodname]#setValue()# and read with the
[methodname]#getValue()# method defined in the [classname]#Property# interface.
The actual value type depends on the component.
The [classname]#Field# 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.
[[components.fields.databinding]]
== Data Binding and Conversions
Fields are strongly coupled with the Vaadin data model. The field value is
handled as a [classname]#Property# of the field component, as documented in
<<dummy/../../../framework/datamodel/datamodel-properties#datamodel.properties,"Properties">>.
Selection fields allow management of the selectable items through the
[classname]#Container# interface.
Fields are __editors__ for some particular type. For example,
[classname]#TextField# allows editing [classname]#String# values. When bound to
a data source, the property type of the data model can be something different,
say an [classname]#Integer#. __Converters__ are used for converting the values
between the representation and the model. They are described in
<<dummy/../../../framework/datamodel/datamodel-properties#datamodel.properties.converter,"Converting
Between Property Type and Representation">>.
[[components.fields.valuechanges]]
== Handling Field Value Changes
[classname]#Field# inherits [classname]#Property.ValueChangeListener# to allow
listening for field value changes and [classname]#Property.Editor# to allow
editing values.
When the value of a field changes, a [classname]#Property.ValueChangeEvent# is
triggered for the field. You should not implement the
[methodname]#valueChange()# method in a class inheriting
[classname]#AbstractField#, as it is already implemented in
[classname]#AbstractField#. You should instead implement the method explicitly
by adding the implementing object as a listener.
[[components.fields.buffering]]
== Field Buffering
Field components implement the [interfacename]#Buffered# and
[interfacename]#BufferedValidatable# interfaces. When buffering is enabled for a
field with [methodname]#setBuffered(true)#, the value is not written to the
property data source before the [methodname]#commit()# method is called for the
field. Calling [methodname]#commit()# also runs validators added to the field,
and if any fail (and the [parameter]#invalidCommitted# is disabled), the value
is not written.
[source, java]
----
form.addComponent(new Button("Commit",
new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
try {
editor.commit();
} catch (InvalidValueException e) {
Notification.show(e.getMessage());
}
}
}));
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.field.buffering.basic[on-line example, window="_blank"].
Calling [methodname]#discard()# reads the value from the property data source to
the current input.
If the fields are bound in a [classname]#FieldGroup# that has buffering enabled,
calling [methodname]#commit()# for the group runs validation on all fields in
the group, and if successful, all the field values are written to the item data
source. See
<<dummy/../../../framework/datamodel/datamodel-itembinding#datamodel.itembinding.buffering,"Buffering
Forms">>.
[[components.fields.validation]]
== Field Validation
The input for a field component can be syntactically or semantically invalid.
Fields implement the [interfacename]#Validatable# interface, which allows
checking validity of the input with __validators__ that implement the
[interfacename]#Validator# interface. You can add validators to fields with
[methodname]#addValidator()#.
[source, java]
----
TextField field = new TextField("Name");
field.addValidator(new StringLengthValidator(
"The name must be 1-10 letters (was {0})",
1, 10, true));
field.setNullRepresentation("");
field.setNullSettingAllowed(true);
layout.addComponent(field);
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.field.validation.basic[on-line example, window="_blank"].
Failed validation is indicated with the error indicator of the field, described
in
<<dummy/../../../framework/application/application-errors#application.errors.error-indicator,"Error
Indicator and Message">>, unless disabled with
[methodname]#setValidationVisible(false)#. Hovering mouse on the field displays
the error message given as a parameter for the validator. If validated
explicitly with [methodname]#validate()#, as described later, the
[classname]#InvalidValueException# is thrown if the validation fails, also
carrying the error message. The value [literal]#++{0}++# in the error message
string is replaced with the invalid input value.
Validators validate the property type of the field after a possible conversion,
not the presentation type. For example, an [classname]#IntegerRangeValidator#
requires that the value type of the property data source is
[classname]#Integer#.
[[components.fields.validation.builtin]]
=== Built-in Validators
Vaadin includes the following built-in validators. The property value type is
indicated.
[classname]#BeanValidator#::
Validates a bean property according to annotations defined in the Bean Validation API 1.0 (JSR-303).
This validator is usually not used explicitly, but they are created implicitly when binding fields in a [classname]#BeanFieldGroup#.
Using bean validation requires an implementation library of the API.
See <<dummy/../../../framework/datamodel/datamodel-itembinding#datamodel.itembinding.beanvalidation,"Bean Validation">> for details.
[classname]#CompositeValidator#::
Combines validators using logical AND and OR operators.
[classname]#DateRangeValidator#: [classname]#Date#::
Checks that the date value is within the range at or between two given dates/times.
[classname]#DoubleRangeValidator#: [classname]#Double#::
Checks that the double value is at or between two given values.
[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.
[classname]#IntegerRangeValidator#: [classname]#Integer#::
Checks that the integer value is at or between two given values.
[classname]#NullValidator#::
Checks whether the value is or is not a null value.
+
For the validator to be meaningful, the component must support inputting null
values. For example, for selection components and [classname]#TextField#,
inputting null values can be enabled with [methodname]#setNullSettingAllowed()#.
You also need to set the representation of null values: in selection components
with [methodname]#setNullSelectionItemId()# and in [classname]#TextField# with
[methodname]#setNullRepresentation()#.
ifdef::web[]
+
Setting field as __required__ can be used for similar effect, and it also
enables an indicator to indicate that a value is required.
endif::web[]
[classname]#RegexpValidator#: [classname]#String#::
Checks that the value matches with the given regular expression.
[classname]#StringLengthValidator#: [classname]#String#::
Checks that the length of the input string is at or between two given lengths.
ifdef::web[]
+
The [parameter]#allowNull# parameter determines whether null values should be
allowed for the string, regardless of the string length. A null value has zero
length, so it will be invalid if the minimum length is greater than zero.
Allowing null value is meaningful only if inputting null values is enabled with
[methodname]#setNullSettingAllowed(true)#, and typically in such case, you want
to set the null representation to empty string with
[methodname]#setNullRepresentation("")#. Note that _this parameter is
deprecated_ and should normally be [parameter]#true#; then you can use
[methodname]#setRequired()# (for the false case) or [classname]#NullValidator#.
endif::web[]
Please see the API documentation for more details.
[[components.fields.validation.automatic]]
=== Automatic Validation
The validators are normally, when [literal]#++validationVisible++# is true for
the field, executed implicitly on the next server request if the input has
changed. If the field is in immediate mode, it (and any other fields with
changed value) are validated immediately when the focus leaves the field.
[source, java]
----
TextField field = new TextField("Name");
field.addValidator(new StringLengthValidator(
"The name must be 1-10 letters (was {0})",
1, 10, true));
field.setImmediate(true);
field.setNullRepresentation("");
field.setNullSettingAllowed(true);
layout.addComponent(field);
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.field.validation.basic[on-line example, window="_blank"].
[[components.fields.validation.explicit]]
=== Explicit Validation
The validators are executed when the [methodname]#validate()# or
[methodname]#commit()# methods are called for the field.
[source, java]
----
// A field with automatic validation disabled
final TextField field = new TextField("Name");
field.setNullRepresentation("");
field.setNullSettingAllowed(true);
layout.addComponent(field);
// Define validation as usual
field.addValidator(new StringLengthValidator(
"The name must be 1-10 letters (was {0})",
1, 10, true));
// Run validation explicitly
Button validate = new Button("Validate");
validate.addClickListener(new ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
field.setValidationVisible(false);
try {
field.validate();
} catch (InvalidValueException e) {
Notification.show(e.getMessage());
field.setValidationVisible(true);
}
}
});
layout.addComponent(validate);
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.field.validation.explicit[on-line example, window="_blank"].
[[components.fields.validation.custom]]
=== Implementing a Custom Validator
You can create custom validators by implementing the [interfacename]#Validator#
interface and implementing its [methodname]#validate()# method. If the
validation fails, the method should throw either
[classname]#InvalidValueException# or [classname]#EmptyValueException#.
[source, java]
----
class MyValidator implements Validator {
@Override
public void validate(Object value)
throws InvalidValueException {
if (!(value instanceof String &&
((String)value).equals("hello")))
throw new InvalidValueException("You're impolite");
}
}
TextField field = new TextField("Say hello");
field.addValidator(new MyValidator());
field.setImmediate(true);
layout.addComponent(field);
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.field.validation.customvalidator[on-line example, window="_blank"].
[[components.fields.validation.fieldgroup]]
=== Validation in Field Groups
If the field is bound to a [classname]#FieldGroup#, described in
<<dummy/../../../framework/datamodel/datamodel-itembinding#datamodel.itembinding,"Creating
Forms by Binding Fields to Items">>, calling [methodname]#commit()# for the
group runs the validation for all the fields in the group, and if successful,
writes the input values to the data source.
(((range="endofrange", startref="term.components.fields")))
|