Class EasyForm<T>

Type Parameters:
T - the bean type
All Implemented Interfaces:
AttachNotifier, DetachNotifier, HasElement, HasSize, HasStyle, Serializable

public class EasyForm<T> extends Composite<VerticalLayout> implements HasSize
A form component that is automatically generated from a POJO definition.

EasyForm introspects the properties of the given bean type (via getter/setter conventions) and creates an appropriate Vaadin form field for each one, configures validations based on JSR-380 (Bean Validation) annotations, and manages data binding through an internal Binder. Properties without both a getter and a setter, or whose type has no registered component factory, are ignored.

All customization is programmatic through a fluent API:


 EasyForm<Person> form = new EasyForm<>(Person.class);
 form.getField("email").withLabel("Email Address").asRequired("Email is required");
 form.setSaveAction(person -> personService.save(person));
 add(form);
 
See Also:
  • Constructor Details

    • EasyForm

      public EasyForm(Class<T> beanType)
      Creates a form whose fields are generated from the properties of the given bean type.
      Parameters:
      beanType - the bean type to generate the form for, not null
      Throws:
      NullPointerException - if beanType is null
      IllegalArgumentException - if beanType cannot be introspected, or if a registered component factory supplies a value that is not a Component
  • Method Details

    • setDefaultComponentFactory

      public static <V> void setDefaultComponentFactory(Class<V> type, SerializableSupplier<HasValue<?,V>> factory)
      Registers a global default component factory for the given value type. The factory applies to all EasyForm instances created after this call, unless overridden per form instance or per property. The supplied component must be a Component.

      The built-in type mappings (e.g. String to TextField) are registered through this same registry and can be replaced by calling this method.

      Type Parameters:
      V - the value type
      Parameters:
      type - the value type to register the factory for, not null
      factory - the factory that creates a component for the type, not null
      Throws:
      NullPointerException - if type or factory is null
    • setDefaultComponentFactory

      public static <V, P> void setDefaultComponentFactory(Class<P> propertyType, SerializableSupplier<HasValue<?,V>> factory, Converter<V,P> converter)
      Registers a global default component factory for the given property type, together with a converter that adapts the component presentation type to the property type (e.g. a NumberField whose Double value is converted to a Long property). The factory applies to all EasyForm instances created after this call, unless overridden per form instance or per property. The supplied component must be a Component.
      Type Parameters:
      V - the presentation value type of the created components
      P - the property type
      Parameters:
      propertyType - the property type to register the factory for, not null
      factory - the factory that creates a component for the type, not null
      converter - the converter from the presentation type to the property type, not null
      Throws:
      NullPointerException - if propertyType, factory or converter is null
    • setComponentFactory

      public <V> void setComponentFactory(Class<V> type, SerializableSupplier<HasValue<?,V>> factory)
      Registers a component factory for the given value type in this form instance, overriding the global defaults. Fields already generated for properties of this type are recreated, unless a custom component was set for them via EasyForm.EasyFormField.withComponent(HasValue). The supplied component must be a Component.
      Type Parameters:
      V - the value type
      Parameters:
      type - the value type to register the factory for, not null
      factory - the factory that creates a component for the type, not null
      Throws:
      NullPointerException - if type or factory is null
      IllegalArgumentException - if the factory supplies a value that is not a Component
    • setComponentFactory

      public <V, P> void setComponentFactory(Class<P> propertyType, SerializableSupplier<HasValue<?,V>> factory, Converter<V,P> converter)
      Registers a component factory for the given property type in this form instance, together with a converter that adapts the component presentation type to the property type, overriding the global defaults. Fields already generated for properties of this type are recreated, unless a custom component was set for them via EasyForm.EasyFormField.withComponent(HasValue). The supplied component must be a Component.
      Type Parameters:
      V - the presentation value type of the created components
      P - the property type
      Parameters:
      propertyType - the property type to register the factory for, not null
      factory - the factory that creates a component for the type, not null
      converter - the converter from the presentation type to the property type, not null
      Throws:
      NullPointerException - if propertyType, factory or converter is null
      IllegalArgumentException - if the factory supplies a value that is not a Component
    • getField

      public <V> EasyForm.EasyFormField<V> getField(String propertyName)
      Returns the configuration wrapper for the field generated for the given property.

      The presentation value type cannot be inferred from the property name, so it is taken from the assignment target and resolves to Object when the result is used directly in a fluent chain. That is harmless for the state and presentation methods, but the methods that take the value type as a parameter — EasyForm.EasyFormField.withValidator(Validator) and EasyForm.EasyFormField.withConverter(Converter) — then reject any argument that is not typed to Object. Use getField(String, Class) in that case.

      Type Parameters:
      V - the presentation value type of the field
      Parameters:
      propertyName - the name of the bean property
      Returns:
      the field wrapper
      Throws:
      IllegalArgumentException - if no property with the given name was discovered
    • getField

      public <V> EasyForm.EasyFormField<V> getField(String propertyName, Class<V> valueType)
      Returns the configuration wrapper for the field generated for the given property, typed to the given presentation value type. The type is inferred from the argument, so the wrapper can be configured in a fluent chain without an explicit type argument:
      
       form.getField("email", String.class).withValidator(new EmailValidator("Invalid email"));
       

      The given type is checked against the value type of the component currently generated for the property, which is the type the field's validators and converters see. Note that this is the presentation type and not necessarily the property type: a Long property bound through the built-in NumberField factory has a presentation type of Double. The check is skipped for properties without a component, and for components whose value type cannot be resolved (such as ComboBox).

      Because the check reflects the component in place at the time of the call, replacing the component for a property is done through getField(String) and EasyForm.EasyFormField.withComponent(HasValue), which types the returned wrapper after the new component.

      Type Parameters:
      V - the presentation value type of the field
      Parameters:
      propertyName - the name of the bean property
      valueType - the expected presentation value type, not null
      Returns:
      the field wrapper
      Throws:
      NullPointerException - if valueType is null
      IllegalArgumentException - if no property with the given name was discovered, or if the component of the property does not have the given presentation value type
    • setFieldOrder

      public void setFieldOrder(String... propertyNames)
      Sets the display order of the fields. Only the listed properties are shown (and included in the binding), in the given order. Repeated names are ignored after their first occurrence.
      Parameters:
      propertyNames - the names of the properties to display, in order
      Throws:
      NullPointerException - if the array or any of its elements is null
      IllegalArgumentException - if any property name is unknown
    • hideFields

      public void hideFields(String... propertyNames)
      Hides the given fields, excluding them from the layout and the binding.
      Parameters:
      propertyNames - the names of the properties to hide
      Throws:
      IllegalArgumentException - if any property name is unknown
    • readOnlyFields

      public void readOnlyFields(String... propertyNames)
      Makes the given fields read-only. Read-only fields are displayed and populated from the bean but cannot be edited.
      Parameters:
      propertyNames - the names of the properties to make read-only
      Throws:
      IllegalArgumentException - if any property name is unknown
    • setBean

      public void setBean(T bean)
      Binds the given bean to the form in edit mode: fields are populated from the bean and valid value changes are written through to it.
      Parameters:
      bean - the bean to edit, or null to clear the form
      Throws:
      IllegalStateException - if a field has a component whose value type cannot be written to its property and no converter was set for it
    • readBean

      public void readBean(T bean)
      Populates the fields with values from the given bean without live binding. Changes are not written to the bean until getValidBean() or the save action runs.
      Parameters:
      bean - the bean to read values from, or null to clear the form
      Throws:
      IllegalStateException - if a field has a component whose value type cannot be written to its property and no converter was set for it
    • getValidBean

      public Optional<T> getValidBean()
      Validates the form and returns the bean with the current field values written to it. If no bean has been set, a new instance is created (the bean type must have an accessible no-args constructor in that case).
      Returns:
      the populated bean, or an empty optional if validation failed
      Throws:
      IllegalStateException - if no bean has been set and the bean type cannot be instantiated, or if a field has a component whose value type cannot be written to its property and no converter was set for it
    • reset

      public void reset()
      Resets the fields to the values of the last bean set through setBean(Object) or readBean(Object). If no bean was set, all fields are cleared.
    • clear

      public void clear()
      Clears all fields. The last bean set is remembered and can be restored with reset().
    • addBeanValidator

      public void addBeanValidator(Validator<? super T> validator)
      Adds a bean-level (cross-field) validator. Bean validators run after all field-level validators have passed.
      Parameters:
      validator - the bean validator to add, not null
      Throws:
      NullPointerException - if validator is null
    • setSaveAction

      public void setSaveAction(SerializableConsumer<T> saveAction)
      Sets the action invoked with the validated bean when the save button is clicked, and makes the save button visible.
      Parameters:
      saveAction - the save action, or null to remove it
    • setCancelAction

      public void setCancelAction(SerializableRunnable cancelAction)
      Sets the action invoked when the cancel button is clicked, and makes the cancel button visible.
      Parameters:
      cancelAction - the cancel action, or null to remove it
    • setSaveButtonText

      public void setSaveButtonText(String text)
      Sets the text of the save button.
      Parameters:
      text - the button text
    • setCancelButtonText

      public void setCancelButtonText(String text)
      Sets the text of the cancel button.
      Parameters:
      text - the button text
    • setSaveButtonVisible

      public void setSaveButtonVisible(boolean visible)
      Overrides the visibility of the save button. By default the button is visible if and only if a save action has been set.
      Parameters:
      visible - whether the save button is visible
    • setCancelButtonVisible

      public void setCancelButtonVisible(boolean visible)
      Overrides the visibility of the cancel button. By default the button is visible if and only if a cancel action has been set.
      Parameters:
      visible - whether the cancel button is visible
    • addButton

      public Button addButton(String text, ComponentEventListener<ClickEvent<Button>> clickListener)
      Adds an extra button to the button bar.
      Parameters:
      text - the button text
      clickListener - the click listener
      Returns:
      the added button
    • addButton

      public Button addButton(String text, Component icon, ButtonVariant variant, ComponentEventListener<ClickEvent<Button>> clickListener)
      Adds an extra button with an icon and a theme variant to the button bar.
      Parameters:
      text - the button text
      icon - the button icon
      variant - the theme variant to apply
      clickListener - the click listener
      Returns:
      the added button
    • setResponsiveSteps

      public void setResponsiveSteps(FormLayout.ResponsiveStep... steps)
      Configures the responsive steps of the internal form layout.
      Parameters:
      steps - the responsive steps
      See Also: