3.5.2.1.47. TextField

TextField is a component for text editing. It can be used both for working with entity attributes and entering/displaying arbitrary textual information.

XML-name of the component: textField

  • An example of a text field with a caption retrieved from the localized messages pack:

    <textField id="nameField" caption="msg://name"/>

    The figure below shows an example of a simple text field.

    gui textField data
  • In Web Client with a Halo-based theme, you can set predefined styles to the TextField component using the stylename attribute either in the XML descriptor or in the screen controller:

    <textField id="textField"
               stylename="borderless"/>

    When setting a style programmatically, select one of the HaloTheme class constants with the TEXTFIELD_ prefix:

    textField.setStyleName(HaloTheme.TEXTFIELD_INLINE_ICON);

    TextField styles:

    • align-center - align the text inside the field to center.

    • align-right - align the text inside the field to the right.

    • borderless - removes the border and background from the text field.

    • inline-icon - moves the default caption icon inside the text field.

    TextField supports automatic case conversion. The caseConvertion attribute can have one of the following values:

    • UPPER - the upper case,

    • LOWER - the lower case,

    • NONE - without conversion (the default value). Use this option to support key-sequence input using IME (for example, for Japanese, Korean or Chinese language).

  • To create a text field connected to data, use dataContainer and property attributes.

    <data>
        <instance id="customerDc" class="com.company.sales.entity.Customer" view="_local">
            <loader/>
        </instance>
    </data>
    <layout>
        <textField dataContainer="customerDc" property="name" caption="msg://name"/>
    </layout>

    As you can see in the example, the screen describes the customerDc data container for Customer entity, which has name attribute. The text field component has a link to the container specified in the dataContainer attribute; property attribute contains the name of the entity attribute that is displayed in the text field.

  • If the field is not connected to an entity attribute (i.e., the data container and attribute name are not set), you can set the data type using the datatype attribute. It is used to format field values. The attribute value accepts any data type registered in the application metadata – see Datatype. Typically, TextField uses the following data types:

    • decimal

    • double

    • int

    • long

    If the datatype attribute is specified for the field and the user enters an incorrect value, the default conversion error message appears.

    As an example, let’s look at a text field with an Integer data type.

    <textField id="integerField" datatype="int" caption="msg://integerFieldName"/>

    If a user enters a value that cannot be interpreted as an integer number, then when the field loses focus, the application will show a default error message.

    gui datatype default message

    Default error messages are specified in the main localized message pack and have the following template: databinding.conversion.error.<type>, e.g.:

    databinding.conversion.error.int = Must be Integer
  • You can specify a custom conversion error message declaratively in the screen XML descriptor using the conversionErrorMessage attribute:

    <textField conversionErrorMessage="This field can work only with Integers" datatype="int"/>

    or programmatically in the screen controller:

    textField.setConversionErrorMessage("This field can work only with Integers");
  • Text field can be assigned a validator – a class implementing Field.Validator interface. The validator limits user input in addition to what is already done by the datatype. For example, to create an input field for positive integer numbers, you need to create a validator class:

    public class PositiveIntegerValidator implements Field.Validator {
        @Override
        public void validate(Object value) throws ValidationException {
            Integer i = (Integer) value;
            if (i <= 0)
                throw new ValidationException("Value must be positive");
        }
    }

    and assign it as a validator to the text field with int datatype:

    <textField id="integerField" datatype="int">
        <validator class="com.sample.sales.gui.PositiveIntegerValidator"/>
    </textField>

    Unlike input check against the data type, validation is performed not when the field looses focus, but after invocation of the field’s validate() method. It means that the field (and the linked entity attribute) may temporarily contain a value that does not satisfy validation conditions (a non-positive number in the example above). This should not be an issue, because validated fields are typically used in editor screens, which automatically invoke validation for all their fields before commit. If the field is located not in an editing screen, the field’s validate() method should be invoked explicitly in the controller.

  • TextField supports TextChangeListener defined in its parent TextInputField interface. Text change events are processed asynchronously after typing in order not to block the typing.

    textField.addTextChangeListener(event -> {
        int length = event.getText().length();
        textFieldLabel.setValue(length + " of " + textField.getMaxLength());
    });
    textField.setTextChangeEventMode(TextInputField.TextChangeEventMode.LAZY);
    gui textfield 2
  • The TextChangeEventMode defines the way the changes are transmitted to the server to cause a server-side event. There are 3 predefined event modes:

    • 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(). A text change event is forced before a possible ValueChangeEvent, even if the user did not keep a pause while entering the text.

    • TIMEOUT - an event is triggered 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.

    • 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.

    • BLUR - an event is triggered when the text field loses focus.

  • EnterPressListener allows you to define an action executed when Enter is pressed:

    textField.addEnterPressListener(enterPressEvent ->
            notifications.create()
                    .withCaption("Enter pressed")
                    .show());
  • ValueChangeListener is triggered on the value changes when the user finished the text input, i.e. after the Enter press or when the component loses focus. An event object of the ValueChangeEvent type is passed to the listener. It has the following methods:

    • getPrevValue() returns the value of the component before the change.

    • getValue() method return the current value of the component.

      textField.addValueChangeListener(stringValueChangeEvent ->
              notifications.create()
                      .withCaption("Before: " + stringValueChangeEvent.getPrevValue() +
                              ". After: " + stringValueChangeEvent.getValue())
                      .show());

      The origin of the ValueChangeEvent can be tracked using isUserOriginated() method.

  • If a text field is linked to an entity attribute (via dataContainer and property), and if the entity attribute has a length parameter defined in the @Column JPA-annotation, then the TextField will limit the maximum length of entered text accordingly.

    If a text field is not linked to an attribute, or if the attribute does not have length value defined, or this value needs to be overridden, then the maximum length of the entered text can be limited using maxLength attribute. The value of "-1" means there are no limitations. For example:

    <textField id="shortTextField" maxLength="10"/>
  • By default, text field trims spaces at the beginning and at the end of the entered string. I.e. if user enters " aaa bbb ", the value of the field returned by the getValue() method and saved to the linked entity attribute will be "aaa bbb". You can disable trimming of spaces by setting the trim attribute to false.

    It should be noted that trimming only works when users enter a new value. If the value of the linked attribute already has spaces in it, the spaces will be displayed until user edits the value.

  • Text field always returns null instead of an entered empty string. Therefore, with the trim attribute enabled, any string containing spaces only will be converted to null.

  • The setCursorPosition() method can be used to focus the field and set the cursor position to the specified 0-based index.