TextField
is one of the most commonly used user
interface components. It is a Field
component that
allows entering textual values using keyboard.
The following example creates a simple text field:
// Create a text field TextField tf = new TextField("A Field"); // Put some initial content in it tf.setValue("Stuff in the field");
See the result in Figure 5.21, “TextField
Example”.
Value changes are handled with a
Property.ValueChangeListener
, as in most other
fields. The value can be acquired with getValue()
directly from the text field, as is done in the example below, or from the
property reference of the event.
// Handle changes in the value tf.addListener(new Property.ValueChangeListener() { public void valueChange(ValueChangeEvent event) { // Assuming that the value type is a String String value = (String) tf.getValue(); // Do something with the value getWindow().showNotification("Value is:", value); } }); // Fire value changes immediately when the field loses focus tf.setImmediate(true);
Much of the API of TextField
is defined in
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.
You can bind a TextField
to any property type that
allows conversion of the value to and from String
with
the getValue()
and
setValue()
methods.
// 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 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");
When you put values in a Form
or
Table
, the
DefaultFieldFactory
creates a
TextField
for almost every property type by
default. However, you often need to make a custom factory that sets the
text field description, immediateness, validation, formatting, and so on.
See Chapter 9, Binding Components to Data for more details on data binding, field
factories for Table
in Section 5.14.3, “Editing the Values in a Table”, and for Form
in the section called “Generating Proper Fields with a FormFieldFactory
”.
The 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
AbstractTextField
level.
Notice that the maximum length setting does not affect the width of the
field. You can set the width with 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. There is no standard way in HTML for setting the width exactly to a
number of letters (in a monospaced font). You can trick your way around
this restriction by putting the text field in an undefined-width
VerticalLayout
together with an undefined-width
Label
that contains a sample text, and setting the
width of the text field as 100%. The layout will get its width from the
label, and the text field will use that.
As with any field, the value of a TextField
can be
set as 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 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
"null
", which essentially warns that you may have
forgotten to initialize your data objects properly.
The setNullSettingAllowed()
controls whether the
user can actually input a null value by using the null value
representation. If the setting is 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.
// Create a text field without setting its value TextField tf = new TextField("Field Energy (J)"); tf.setNullRepresentation("-- null-point energy --"); // The null value is actually the default tf.setValue(null); // Allow user to input the null value by // its representation tf.setNullSettingAllowed(true); // Feedback to see the value Label value = new Label(tf); value.setCaption("Current Value:");
The Label
, which is bound to the value of the
TextField
, displays a null value as empty. The
resulting user interface is shown in Figure 5.23, “Null Value Representation”.
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.
Text change events are received with a
TextChangeListener
, as is done in the following
example that demonstrates how to create a text length counter:
// 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.toString().length() + " of " + tf.getMaxLength()); // Display the current length interactively in the counter tf.addListener(new TextChangeListener() { public void textChange(TextChangeEvent event) { int len = event.getText().length(); counter.setValue(len + " of " + tf.getMaxLength()); } }); // This is actually the default tf.setTextChangeEventMode(TextChangeEventMode.LAZY);
The result is shown in Figure 5.24, “Text Change Events”.
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.
You can set the text change event mode of a
TextField
with
setTextChangeEventMode()
. The allowed modes are
defined in TextChangeEventMode
class and are the
following:
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
setInputEventTimeout()
. As with the
TIMEOUT
mode, a text change event is
forced before a possible
ValueChangeEvent
, even if the user did
not keep a pause while entering the text.
This is the default mode.
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
setInputEventTimeout()
.
If a ValueChangeEvent
would occur
before the timeout period, a
TextChangeEvent
is triggered before it,
on the condition that the text content has changed since the
previous TextChangeEvent
.
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.
.v-textfield { }
The HTML structure of TextField
is extremely simple,
consisting only of an element with v-textfield
style.
For example, the following custom style uses dashed border:
.v-textfield-dashing { border: thin dashed; background: white; /* Has shading image by default */ }
The result is shown in Figure 5.25, “Styling TextField with CSS”.
The style name for TextField
is also used in
several components that contain a text input field, even if the text input
is not an actual TextField
. This ensures that the
style of different text input boxes is similar.