123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- ---
- 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 the features defined in the
- [classname]#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%]
-
- /////////////////////////////////////////////////////////////////////////////
- // Disabled because everything has changed in Vaadin 8.
- // Revise
- /////////////////////////////////////////////////////////////////////////////
- ifdef::disabled[]
-
- The description of the field interfaces and base classes is broken down in the
- following sections.
-
- [[components.fields.field]]
- == The [classname]#Field# Interface
-
- The [classname]#Field# interface inherits the [classname]#Component#
- superinterface and also the [classname]#HasValue# 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]#HasValue# 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.valuechanges]]
- == Handling Field Value Changes
-
- [classname]#Field# provides two methods for listening to changes to the field value:
- [methodname]#onValueChange# and [methodname]#addValueChangeListener#. The difference
- is that the former takes a [interfacename]#Consumer# object that only receives the new value;
- the latter, on the other hand, takes an [interfacename]#EventListener# that gets
- a [classname]#ValueChange# event instance containing extra information about the event.
-
- Both methods return 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();
-
- // Just echo in the label anything the user enters
- textField.onValueChange(echo::setValue);
-
- // Add a more complex listener
- 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<Person> binder = new Binder<>();
-
- // Bind nameField to the Person.name property
- // by specifying its getter and setter
- binder.addField(nameField)
- .bind(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;
- ----
-
- == 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]#addValidator#
- method on the [interfacename]#Binding# object returned by [methodname]#Binder.addField#.
-
- [source, java]
- ----
- binder.addField(nameField)
- .addValidator(new StringLengthValidator(2, 20,
- "Name must be between 2 and 20 characters long"))
- .bind(Person::getName, Person::setName);
- ----
-
- 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">>. 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.
-
- [[components.fields.validation.builtin]]
- === Built-in Validators
-
- Vaadin includes the following built-in validators. The property value type is
- indicated.
-
- [classname]#RangeValidator#: [classname]#Comparable#::
- Checks that the given [interfacename]#Comparable# value is at or between two given values.
-
- [classname]#StringLengthValidator#: [classname]#String#::
- Checks that the length of the input string is at or between two given lengths.
-
- [classname]#RegexpValidator#: [classname]#String#::
- Checks that the value matches the given regular expression.
-
- [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.
-
- === 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<String> {
- @Override
- public Result<String> apply(String input) {
- 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]#addValidator# overload that creates a
- validator from a boolean function and an error message.
-
- [source, java]
- ----
- binder.addField(nameField)
- .addValidator(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
- <<dummy/../../../framework/datamodel/datamodel-properties#datamodel.properties.converter,"Converting
- Between Model and Presentation Types">>.
-
-
- endif::disabled[]
-
- (((range="endofrange", startref="term.components.fields")))
|