summaryrefslogtreecommitdiffstats
path: root/documentation/components/components-textfield.asciidoc
blob: db3d93aebac392646234094d5fd00c5ff2ceea14 (plain)
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
---
title: TextField
order: 9
layout: page
---

[[components.textfield]]
= [classname]#TextField#

ifdef::web[]
[.sampler]
image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/data-input/text-input/text-field]
endif::web[]

((("[classname]#TextField#", id="term.components.textfield", range="startofrange")))

[classname]#TextField# is one of the most commonly used user interface
components. It is a [classname]#Field# component that allows entering textual
values using keyboard.

The following example creates a simple text field:

[source, java]
----
// Create a text field
TextField tf = new TextField("A Field");
        
// Put some initial content in it
tf.setValue("Stuff in the field");
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.textfield.basic[on-line example, window="_blank"].

The result is shown in <<figure.components.textfield.basic>>.

[[figure.components.textfield.basic]]
.[classname]#TextField# Example
image::img/textfield-example.png[]

Value changes are handled with a [classname]#Property.ValueChangeListener#, as
in most other fields. The value can be acquired with [methodname]#getValue()#
directly from the text field, as is done in the example below, or from the
property reference of the event.

[source, java]
----
// Handle changes in the value
tf.addValueChangeListener(new Property.ValueChangeListener() {
    public void valueChange(ValueChangeEvent event) {
        // Assuming that the value type is a String
        String value = (String) event.getProperty().getValue();

        // Do something with the value
        Notification.show("Value is: " + value);
    }
});

// Fire value changes immediately when the field loses focus
tf.setImmediate(true);
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.textfield.inputhandling[on-line example, window="_blank"].

As with other event listeners, you can use lambda expression with one parameter
to handle the events in Java 8.

Much of the API of [classname]#TextField# is defined in
[classname]#AbstractTextField#, which allows different kinds of text input
fields, such as rich text editors, which do not share all the features of the
single-line text fields.

[[figure.components.textfield.api]]
.Text Field Class Relationships
image::img/textfield-diagram-hi.png[width=50%]

[[components.textfield.databinding]]
== Data Binding

[classname]#TextField# edits [classname]#String# values, but you can 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">>.

[source, java]
----
// Have an initial data model. As Double is unmodificable and
// doesn't support assignment from String, the object is
// reconstructed in the wrapper when the value is changed.
Double trouble = 42.0;
        
// Wrap it in a property data source
final ObjectProperty<Double> property =
    new ObjectProperty<Double>(trouble);
        
// Create a text field bound to it
// (StringToDoubleConverter is used automatically)
TextField tf = new TextField("The Answer", property);
tf.setImmediate(true);

// Show that the value is really written back to the
// data source when edited by user.
Label feedback = new Label(property);
feedback.setCaption("The Value");
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.textfield.databinding[on-line example, window="_blank"].

When you put a [classname]#Table# in editable mode or create fields with a
[classname]#FieldGroup#, the [classname]#DefaultFieldFactory# creates a
[classname]#TextField# for almost every property type by default. You often need
to make a custom factory to customize the creation and to set the field tooltip,
validation, formatting, and so on.

See
<<dummy/../../../framework/datamodel/datamodel-overview.asciidoc#datamodel.overview,"Binding
Components to Data">> for more details on data binding, field factories for
[classname]#Table# in
<<dummy/../../../framework/components/components-table#components.table.editing,"Editing
the Values in a Table">>, and
<<dummy/../../../framework/datamodel/datamodel-itembinding#datamodel.itembinding,"Creating
Forms by Binding Fields to Items">> regarding forms.

[[components.textfield.length]]
== String Length

The [methodname]#setMaxLength()# method sets the maximum length of the input
string so that the browser prevents the user from entering a longer one. As a
security feature, the input value is automatically truncated on the server-side,
as the maximum length setting could be bypassed on the client-side. The maximum
length property is defined at [classname]#AbstractTextField# level.

Notice that the maximum length setting does not affect the width of the field.
You can set the width with [methodname]#setWidth()#, as with other components.
Using __em__ widths is recommended to better approximate the proper width in
relation to the size of the used font, but the __em__ width is not exactly the
width of a letter and varies by browser and operating system. There is no standard
way in HTML for setting the width exactly to a number of letters (in a monospaced font).

[[components.textfield.nullvalues]]
== Handling Null Values

((("Null representation", id="term.components.textfield.nullvalues", range="startofrange")))

((("[methodname]#setNullRepresentation()#")))
As with any field, the value of a [classname]#TextField# can be set as
[parameter]#null#. This occurs most commonly when you create a new field without
setting a value for it or bind the field value to a data source that allows null
values. In such case, you might want to show a special value that stands for the
null value. You can set the null representation with the
[methodname]#setNullRepresentation()# method. Most typically, you use an empty
string for the null representation, unless you want to differentiate from a
string that is explicitly empty. The default null representation is "
[literal]#++null++#", which essentially warns that you may have forgotten to
initialize your data objects properly.

((("[methodname]#setNullSettingAllowed()#")))
The [methodname]#setNullSettingAllowed()# controls whether the user can actually
input a null value by using the null value representation. If the setting is
[literal]#++false++#, which is the default, inputting the null value
representation string sets the value as the literal value of the string, not
null. This default assumption is a safeguard for data sources that may not allow
null values.

[source, java]
----
// Have a property with null value
ObjectProperty<Double> dataModel =
    new ObjectProperty<Double>(new Double(0.0));
dataModel.setValue(null); // Have to set it null here

// Create a text field bound to the null data
TextField tf = new TextField("Field Energy (J)", dataModel);
tf.setNullRepresentation("-- null-point --");

// Allow user to input the null value by its representation
tf.setNullSettingAllowed(true);
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.textfield.nullvaluerepresentation[on-line example, window="_blank"].

The [classname]#Label#, which is bound to the value of the
[classname]#TextField#, displays a null value as empty. The resulting user
interface is shown in <<figure.components.textfield.nullvalues>>.

[[figure.components.textfield.nullvalues]]
.Null Value Representation
image::img/textfield-nullrepresentation.png[]

(((range="endofrange", startref="term.components.textfield.nullvalues")))

[[components.textfield.textchangeevents]]
== Text Change Events

((("[classname]#Text change events#", id="term.components.textfield.textchangeevents", range="startofrange")))

Often you want to receive a change event immediately when the text field value
changes. The __immediate__ mode is not literally immediate, as the changes are
transmitted only after the field loses focus. In the other extreme, using
keyboard events for every keypress would make typing unbearably slow and also
processing the keypresses is too complicated for most purposes. __Text change
events__ are transmitted asynchronously soon after typing and do not block
typing while an event is being processed.

((([classname]#TextChangeListener#)))
Text change events are received with a [classname]#TextChangeListener#, as is
done in the following example that demonstrates how to create a text length
counter:

[source, java]
----
// Text field with maximum length
final TextField tf = new TextField("My Eventful Field");
tf.setValue("Initial content");
tf.setMaxLength(20);

// Counter for input length
final Label counter = new Label();
counter.setValue(tf.getValue().length() +
                 " of " + tf.getMaxLength());

// Display the current length interactively in the counter
tf.addTextChangeListener(new TextChangeListener() {
    public void textChange(TextChangeEvent event) {
        int len = event.getText().length();
        counter.setValue(len + " of " + tf.getMaxLength());
    }
});

// The lazy mode is actually the default
tf.setTextChangeEventMode(TextChangeEventMode.LAZY);
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.textfield.textchangeevents.counter[on-line example, window="_blank"].

The result is shown in <<figure.components.textfield.textchangeevents>>.

[[figure.components.textfield.textchangeevents]]
.Text Change Events
image::img/textfield-textchangeevents.png[]

The __text change event mode__ defines how quickly the changes are transmitted
to the server and cause a server-side event. Lazier change events allow sending
larger changes in one event if the user is typing fast, thereby reducing server
requests.

((([classname]#TextChangeEventMode#)))
You can set the text change event mode of a [classname]#TextField# with
[methodname]#setTextChangeEventMode()#. The allowed modes are defined in
[classname]#TextChangeEventMode# enum and are as follows:

[parameter]#TextChangeEventMode.LAZY#(default):: An event is triggered when there is a pause in editing the text. The length of
the pause can be modified with [methodname]#setInputEventTimeout()#. As with the
[parameter]#TIMEOUT# mode, a text change event is forced before a possible
[classname]#ValueChangeEvent#, even if the user did not keep a pause while
entering the text.

+
This is the default mode.

[parameter]#TextChangeEventMode.TIMEOUT#:: A text change in the user interface causes the event to be communicated to the
application after a timeout period. If more changes are made during this period,
the event sent to the server-side includes the changes made up to the last
change. The length of the timeout can be set with
[methodname]#setInputEventTimeout()#.

+
If a [classname]#ValueChangeEvent# would occur before the timeout period, a
[classname]#TextChangeEvent# is triggered before it, on the condition that the
text content has changed since the previous [classname]#TextChangeEvent#.

[parameter]#TextChangeEventMode.EAGER#:: An event is triggered immediately for every change in the text content,
typically caused by a key press. The requests are separate and are processed
sequentially one after another. Change events are nevertheless communicated
asynchronously to the server, so further input can be typed while event requests
are being processed.

(((range="endofrange", startref="term.components.textfield.textchangeevents")))

[[components.textfield.css]]
== CSS Style Rules

[source, css]
----
.v-textfield { }
----

The HTML structure of [classname]#TextField# is extremely simple, consisting
only of an element with the [literal]#++v-textfield++# style.

For example, the following custom style uses dashed border:

[source, css]
----
.v-textfield-dashing {
    border:     thin dashed;
    background: white; /* Has shading image by default */
}
----
See the http://demo.vaadin.com/book-examples-vaadin7/book#component.textfield.css[on-line example, window="_blank"].

The result is shown in <<figure.components.textfield.css>>.

[[figure.components.textfield.css]]
.Styling TextField with CSS
image::img/textfield-css.png[]

The style name for [classname]#TextField# is also used in several components
that contain a text input field, even if the text input is not an actual
[classname]#TextField#. This ensures that the style of different text input
boxes is similar.

(((range="endofrange", startref="term.components.textfield")))