A property of a Java type can be another object, or a list of objects. The examples on this page use the Person record on Forms, which has an address and a list of phone numbers:
Source code
Address.java
package com.vaadin.demo.fusion.forms.person;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
public record Address(@NotBlank String street,
@Pattern(regexp = "\\d{5}", message = "Enter five digits") String postalCode,
@NotBlank String city) {
}
Source code
PhoneNumber.java
package com.vaadin.demo.fusion.forms.person;
import jakarta.validation.constraints.NotBlank;
public record PhoneNumber(@NotBlank String number, String label) {
}
Keep nested objects and lists non-nullable, for example by annotating their package with @NullMarked. The useFormArrayPart() hook doesn’t accept the model of a nullable list.
Nested Objects
The model of an object property has models for the properties of the object, so a field can bind to them directly, such as field(model.address.street). The name of the field is the path of the property, address.street. The errors of the server use the same path, so that they appear in the right field.
To split a form into components, pass the model of a nested object to a component, and call useFormPart() there. The part has a field() function of its own, and the state of the nested object, as described in Form State. Type the property of the component with the generated model type, which has the same name as the model:
For a list or an array, call useFormArrayPart() with its model. Besides the state of the list, the result has an items property, with a model for each item. Bind the fields of each item to its model, for example in a component of their own:
To add or remove items, call setValue() with a new list. The default value of a model, such as PhoneNumberModel[$defaultValue], is an empty item. Import $defaultValue from @vaadin/hilla-models:
The models in items follow the positions in the list, so use the index as the key. The name of a field in an item contains the index, such as phoneNumbers.0.number.