Input Components

This section documents the current Vaadin release line — Vaadin 24 LTS / 25.x, Java 17+, Spring Boot 3 / Jakarta EE 10 — as published at the official Vaadin documentation, which is the reference these pages are written and verified against. No specific patch version is pinned. Flow (server-side Java) is the authoring style used throughout, with Hilla / React shown where it differs; Vaadin 7 and the pre-Flow architecture appear only as migration contrast.

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production, since Vaadin ships major releases roughly twice a year and its ecosystem iterates.

This section’s bibliography lists the reference material consulted while preparing these pages.

Vaadin ships about twenty ready-made input components — one per data type a business form needs. They all implement the same HasValue contract, so Binder drives any of them the same way. This page follows the individual component pages under Components, starting with Text Field; for wiring fields to a bean see Data Binding.

The HasValue contract

Every field implements HasValue<E, V>: getValue() / setValue(v), an empty value (isEmpty(), clear()), addValueChangeListener(…​), and setReadOnly(boolean) / setRequiredIndicatorVisible(boolean). A value-change event reports the old value, the new value, and whether the change came from the client (isFromClient()).

TextField name = new TextField("Name");
name.addValueChangeListener(e -> {
    String old = e.getOldValue();
    String current = e.getValue();
    boolean typed = e.isFromClient();   // false for setValue(...) from server code
    Notification.show(old + " -> " + current);
});

Because the API is uniform, a helper method can accept any field:

void logChanges(HasValue<?, ?> field) {
    field.addValueChangeListener(e -> log.info("value = {}", e.getValue()));
}

Value-change modes

Text-like fields (TextField, TextArea, EmailField, PasswordField, NumberField, IntegerField, BigDecimalField) expose a ValueChangeMode that decides when the server hears about typing:

Mode When the value-change event fires

ValueChangeMode.ON_CHANGE (default)

On blur, and on Enter.

ValueChangeMode.ON_BLUR

Only when the field loses focus.

ValueChangeMode.EAGER

On every keystroke — one round trip per character.

ValueChangeMode.LAZY

On every keystroke, but debounced by setValueChangeTimeout(ms).

TextField search = new TextField("Search");
search.setValueChangeMode(ValueChangeMode.LAZY);
search.setValueChangeTimeout(300);      // fire 300 ms after the user stops typing
search.addValueChangeListener(e -> results.setItems(service.search(e.getValue())));

LAZY is the right choice for as-you-type filtering; ON_CHANGE for ordinary form fields.

Shared field features

The field pages document a common set of properties, shown here on a TextField but available on almost every field:

TextField iban = new TextField("IBAN");
iban.setRequiredIndicatorVisible(true);          // the * marker (Binder.asRequired adds the rule)
iban.setHelperText("Two-letter country code followed by up to 32 characters");
iban.setErrorMessage("Not a valid IBAN");        // shown while the field is invalid
iban.setPrefixComponent(VaadinIcon.MONEY.create());
iban.setSuffixComponent(new Span("verified"));
iban.setClearButtonVisible(true);
iban.setReadOnly(true);
iban.setPlaceholder("DE89 3704 ...");
iban.setTooltipText("Shown on hover and focus");  // https://vaadin.com/docs/latest/components/tooltip

Validation constraints such as setMaxLength, setPattern, setMin / setMax and setRequired participate in Binder validation because these components implement HasValidator — see Data Binding.

Text fields

TextField (single line), TextArea (multi-line, setMaxRows), EmailField (built-in email pattern) and PasswordField (masked, with a reveal button) all produce String values.

TextField fullName = new TextField("Full name");
fullName.setMaxLength(60);

TextArea notes = new TextArea("Notes");
notes.setMaxRows(6);

EmailField email = new EmailField("Email");        // https://vaadin.com/docs/latest/components/email-field

PasswordField password = new PasswordField("Password");
password.setRevealButtonVisible(false);            // https://vaadin.com/docs/latest/components/password-field

add(fullName, notes, email, password);

Numeric fields

NumberField yields Double, IntegerField yields Integer, and BigDecimalField yields BigDecimal for money and other exact values. All three accept setMin, setMax, setStep and an optional step-controls spinner.

NumberField weight = new NumberField("Weight (kg)");
weight.setStep(0.1);
weight.setStepButtonsVisible(true);

IntegerField quantity = new IntegerField("Quantity");
quantity.setMin(1);
quantity.setMax(99);

BigDecimalField price = new BigDecimalField("Price");
price.setValue(new BigDecimal("19.99"));

For a text field that stores a number, bind a plain TextField through a Converter instead — see Data Binding.

Boolean and choice fields

  • Checkbox — a single Boolean.

  • CheckboxGroup<T> — a Set<T> of selected items.

  • RadioButtonGroup<T> — one T, all options visible.

  • Select<T> — one T from a drop-down (no free text).

  • ListBox<T> / MultiSelectListBox<T> — a scrollable, unstyled list for one or many T.

Checkbox subscribe = new Checkbox("Subscribe to the newsletter");

CheckboxGroup<String> roles = new CheckboxGroup<>("Roles");
roles.setItems("ADMIN", "EDITOR", "VIEWER");
Set<String> chosen = roles.getValue();

RadioButtonGroup<Priority> priority = new RadioButtonGroup<>("Priority");
priority.setItems(Priority.values());
priority.setRenderer(new TextRenderer<>(Priority::getLabel));

Select<Country> country = new Select<>();
country.setLabel("Country");
country.setItems(countryService.findAll());
country.setItemLabelGenerator(Country::getName);
country.setEmptySelectionAllowed(true);

Date and time fields

DatePicker gives a LocalDate, TimePicker a LocalTime, and DateTimePicker a LocalDateTime. DatePicker supports setMin / setMax, a custom setI18n(…​) for locale text, and setInitialPosition(…​).

DatePicker birthDate = new DatePicker("Date of birth");
birthDate.setMax(LocalDate.now());
birthDate.setValue(LocalDate.of(1990, 1, 1));

TimePicker openingTime = new TimePicker("Opens at");
openingTime.setStep(Duration.ofMinutes(30));

DateTimePicker deadline = new DateTimePicker("Deadline");
deadline.setDatePlaceholder("Date");
deadline.setTimePlaceholder("Time");

ComboBox and lazy loading

ComboBox<T> is a single-select drop-down with type-ahead filtering. For a small list, setItems(…​) holds every item in server memory and filters in the browser:

ComboBox<Country> country = new ComboBox<>("Country");
country.setItems(countryService.findAll());
country.setItemLabelGenerator(Country::getName);

For a large table, register lazy callbacks: ComboBox passes the current filter text, offset and limit in a Query, and only the matching page is fetched. This is the ComboBoxLazyDataView path described on the Combo Box page.

ComboBox<Customer> customer = new ComboBox<>("Customer");
customer.setItemLabelGenerator(Customer::getName);
customer.setItems(
        query -> customerService
                .findByNameLike(query.getFilter().orElse(""),
                        query.getOffset(), query.getLimit())
                .stream(),
        query -> customerService.countByNameLike(query.getFilter().orElse("")));

MultiSelectComboBox<T> is the same component returning a Set<T>, with chips for the chosen items:

MultiSelectComboBox<String> tags = new MultiSelectComboBox<>("Tags");
tags.setItems("java", "flow", "hilla", "spring");
Set<String> selectedTags = tags.getValue();

setAllowCustomValue(true) plus an addCustomValueSetListener lets the user add entries that are not in the list.

Upload

Upload pairs with a Receiver that returns the OutputStream each incoming file is written to. MemoryBuffer keeps one file in memory; MultiFileMemoryBuffer accepts several.

MemoryBuffer buffer = new MemoryBuffer();
Upload upload = new Upload(buffer);
upload.setAcceptedFileTypes("image/png", "image/jpeg");
upload.setMaxFileSize(5 * 1024 * 1024);

upload.addSucceededListener(event -> {
    String name = event.getFileName();
    try (InputStream in = buffer.getInputStream()) {
        avatarService.store(name, in.readAllBytes());
    }
});
upload.addFileRejectedListener(event -> Notification.show(event.getErrorMessage()));

For an upload straight to disk or a service, provide a custom Receiver that returns your own stream. File downloads are covered in REST and Services.

Slider

Slider picks a numeric value by dragging a thumb along a track; setMin, setMax and setStep bound it, and a range variant with two thumbs selects an interval.

Slider volume = new Slider("Volume");
volume.setMin(0);
volume.setMax(100);
volume.setStep(5);
volume.setValue(60d);
volume.addValueChangeListener(e -> player.setVolume(e.getValue()));

For an integer-only control with a spinner instead of a track, use IntegerField with setStepButtonsVisible(true).

In Hilla / React: the same components are imported from @vaadin/react-components (<TextField>, <ComboBox>, <DatePicker>, <Upload>, …​). Binding is value / onValueChanged or the @vaadin/hilla-react-form field(…​) directive rather than Binder; see Hilla and React Views and React Reference.

See also