Creating data-intensive UIs with forms and data grids can be difficult. Developers need to consider many aspects—business logic, data consistency, usability, accessibility, maintainability—to create a good experience for users and keep the code complexity manageable. That’s why frameworks like Vaadin offer special support for data binding and form validation.
Vaadin 17 introduces a TypeScript API for form binding. It includes the best parts of the tried-and-true Java Binder API: reliable code completion, type safety, flexible validation, and direct access to the backend data. In addition to this, as TypeScript views run in the browser, the new API offers low latency client-side validation that does not require a stable network connection and works offline.
No boilerplate: use the data model you already have
When creating forms, you can use the data types you already have in Java. There is no need to define the same types again in order to use them in TypeScript. Vaadin automatically generates TypeScript types for data entities and form models, based on the Java data model. This happens during the frontend build phase for any Java classes that are used in at least one @Endpoint
(either as a return type, or as a type of one of the arguments).
For example, a Java Order
entity type can be used directly when creating forms. Both the Order
entity type and the OrderModel
form model type are generated and can be imported with a single line.
Order.java
public class Order {
private Customer customer;
private List<OrderLine> lines;
private LocalDate dueDate;
private LocalTime dueTime;
private String notes;
// ... constructor, getters, setters, etc
}
order-form.ts
import { Binder, field } from '@vaadin/form';
import OrderModel from
'../generated/com/example/forms/entities/OrderModel';
private binder = new Binder(this, OrderModel);
Code completion and type safety in TypeScript
Vaadin forms use typed form models, where each form field is referred to with a named model property, like model.customer.email
. This enables reliable code completion and prevents typos and hard-to-detect errors that are typical when using plain strings like 'customer.email'
.
Note the use of the ...
spread operator. Similar to how it works in JavaScript, here it binds several properties and events of the <vaadin-text-field>
web component with a single attribute.
Another benefit of this approach is automatic type checking, based on the known model property types. In the example below, the type of the value
parameter in the validator is inferred from the known type of the model.customer
property.
Shared validators for server and client: more secure and easier to maintain
The user input is validated to conform to the data model as early as possible: in many cases this occurs immediately (as the user finishes typing). All validation constraints on the Java data model, such as @NotBlank
, @Email
and other JSR-380 annotations, are taken into account automatically.
The example below shows a string length constraint on the fullName
property of a Customer
Java type.
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
public class Customer {
@NotBlank
@Size(max = 32)
private String fullName;
// ... more properties, constructor, getters, setters, etc
}
This constraint is automatically taken into account in any form created using the Vaadin form-binding API in TypeScript.
private binder = new Binder(this, OrderModel);
render() {
const { model } = this.binder;
return html`
<vaadin-text-field label="Customer Name"
...="${field(model.customer.fullName)}">
</vaadin-text-field>
`;
}
Vaadin Binder automatically applies this constraint, immediately as the user types in the bound field: it is evaluated in the browser, with minimal latency, and without network round trips.
Vaadin offers client-side implementations for most of the built-in JSR-380 validators, in order to reduce latency. In addition, all constraints are always re-validated on the server-side to ensure data consistency.
The TypeScript form-binding API is available in Vaadin 17+ applications from the @vaadin/form
module. For more information on type safety, generated form models, validation, support for array properties and reacting to form state changes, please check out the docs. And try it for yourself: download a project from start.vaadin.com and see it in action there.