--- 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. <> illustrates the inheritance relationships and the important interfaces and base classes. [[figure.components.fields]] .Field Components image::img/field-class-hierarchy.png[width=100%, scaledwidth=100%] 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 <>). In addition to the component features inherited from [classname]#AbstractComponent#, it implements the features defined in the [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 [interfacename]#HasValue# interface and field components extending [classname]#AbstractField] is broken down in the following sections. [[components.fields.field]] == The [interfacename]#HasValue# Interface 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 value with the [methodname]#setValue()# and read it with the [methodname]#getValue()# method defined in the [classname]#HasValue# interface. The [classname]#HasValue# interface defines a number of properties, which you can access with the corresponding setters and getters. [methodname]#readOnly#:: Set the component to be read-only, meaning that the value is not editable. [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 <>), 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. [[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] ---- TextField textField = new TextField(); Label echo = new Label(); textField.addValueChangeListener(event -> { String origin = event.isUserOriginated() ? "user" : "application"; String message = origin + " entered the following: " + event.getValue(); Notification.show(message); }); ---- [[components.fields.databinding]] == Binding Fields to Data Fields can be grouped into _forms_ and coupled with business data objects with the [classname]#Binder# class. When a field is bound to a property using [classname]#Binder#, it gets its default value from the property, and is stored to the property either manually via the [methodname]#Binder.save# method, or automatically every time the value changes. [source, java] ---- class Person { private String name; public String getName() { /* ... */ } public void setName(String) { /* ... */ } } TextField nameField = new TextField(); Binder binder = new Binder<>(); // Bind nameField to the Person.name property // by specifying its getter and setter 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); ---- For more information on data binding, see <> == Validating Field Values User input may be syntactically or semantically invalid. [classname]#Binder# allows adding a chain of one or more __validators__ for 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( "Name must be between 2 and 20 characters long", 2, 20)) .bind(Person::getName, Person::setName); ---- Failed validation is by default indicated with the error indicator of the field, described in <>. 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. === Implementing Custom Validators Validators implement the [interfacename]#Validator# interface that simply extends [interfacename]#java.util.function.Function#, returning a special type called [interfacename]#Result#. This return type represents the validation outcome: whether or not the given input was valid. [source, java] ---- class MyValidator implements Validator { @Override public Result apply(String value, ValueContext context) { if(input.length() == 6) { return Result.ok(input); } else { return Result.error( "Must be exactly six characters long"); } } } ---- Because [methodname]#Result.ok# takes the valid value as an argument, a validator can also do some sanitization on valid inputs, such as removing leading and trailing whitespace from a string. Since [interfacename]#Validator# is a functional interface, you can often simply write a lambda expression instead of a full class declaration. There is also an [methodname]#withValidator# overload that creates a validator from a boolean function and an error message. [source, java] ---- binder.forField(nameField) .withValidator(name -> name.length() < 20, "Name must be less than 20 characters long") .bind(Person::getName, Person::setName); ---- == Converting Field Values Field values are always of some particular type. For example, [classname]#TextField# allows editing [classname]#String# values. When bound to 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 <>. (((range="endofrange", startref="term.components.fields")))