Class FieldBuilder<T>

  • Type Parameters:
    T - backing object type
    All Implemented Interfaces:
    Serializable

    public class FieldBuilder<T>
    extends Object
    implements Serializable
    Automatically builds a Binder and configures and binds fields based on method annotations.

    FieldBuilder annotations allow for the automatic construction of forms for editing the annotated bean type. Annotations specify how bean properties should be edited in a form. As a result, all information about how to edit a Java type, including field customization such as captions, widths, etc., can be specified declaratively.

    @ProvidesField vs. @FieldBuilder.Foo

    FieldBuilder supports two types of annotations that can tell it how to construct fields: the @ProvidesField annotates a method that knows how to build a HasValue widget suitable for editing the named bean property. This is the most general approach, but it requires adding code.

    The @FieldBuilder.Foo annotations are the purely declarative way to specify how to construct a field. These annotations annotate Java bean property getter methods, and specify how to configure a HasValue widget that will edit the annotated property. The annotations @FieldBuilder.AbstractComponent, @FieldBuilder.AbstractField, @FieldBuilder.ComboBox, etc. mirror to the Vaadin widget class hierarchy and configure the corresponding widget properties (separate annotations were used for each class in the hierarchy because Java doesn't allow annotation inheritance).

    Configuring the Binding

    In addition to configuring the fields associated with each bean property in the Binder, you may also want to configure the bindings themselves, for example, to specify a Converter or Validator. The @FieldBuilder.Binding annotation allows you to configure the binding, using properties relevant to Binder.BindingBuilder.

    @FieldBuilder.Binding also allows you to specify the order in which the fields should appear in the form.

    Example

    A simple example shows how these annotations are used:

    
     // Use a 10 row TextArea to edit the "description" property
     @FieldBuilder.AbstractComponent(caption = "Description:")
     @FieldBuilder.TextArea(rows = 10)
     @FieldBuilder.Binding(required = "Description is mandatory", validator = MyValidator.class)
     public String getDescription() {
         return this.description;
     }
    
     // Use an enum combo box to edit the gender property
     @FieldBuilder.EnumComboBox(caption = "Gender:")
     @FieldBuilder.Binding(required = "Gender is mandatory", order = 3.0)
     public Gender getGender() {
         return this.gender;
     }
    
     // Use my own custom field to edit the "foobar" property
     public Foobar getFoobar() { ... }
     public void setFoobar(Foobar foobar) { ... }
    
     @FieldBuilder.ProvidesField("foobar")
     private static MyCustomField createFoobarField() {
         ...
     }
     

    Building the Form

    Use FieldBuilder.buildAndBind() to setup the Binder, and then add the bound fields to your form:

    
     // Create fields based on FieldBuilder.* annotations
     Binder<Person> binder = new FieldBuilder(Person.class).buildAndBind().getBinder();
    
     // Layout the fields in a form
     FormLayout layout = new FormLayout();
     layout.add((Component)binder.getBinding("description").get().getField());
     layout.add((Component)binder.getBinding("gender").get().getField());
     layout.add((Component)binder.getBinding("foobar").get().getField());
    
     // Bind a value
     Person person = new Person("Joe Smith", 100);
     binder.setBean(person);
     

    To use the generated fields as editor bindings for a Grid, see setEditorBindings(com.vaadin.ui.Grid<T>). For declarative configuration of Grid columns, see @GridColumn.

    See Also:
    FieldBuilder.AbstractDateField, FieldBuilder.AbstractTextField, FieldBuilder.CheckBox, FieldBuilder.CheckBoxGroup, FieldBuilder.ComboBox, FieldBuilder.DateField, FieldBuilder.DateTimeField, FieldBuilder.EnumComboBox, FieldBuilder.InlineDateField, FieldBuilder.ListSelect, FieldBuilder.PasswordField, FieldBuilder.RadioButtonGroup, FieldBuilder.RichTextArea, FieldBuilder.Slider, FieldBuilder.TextArea, FieldBuilder.TextField, GridColumn, Serialized Form
    • Constructor Detail

      • FieldBuilder

        public FieldBuilder​(Class<T> type)
        Constructor.
        Parameters:
        type - backing object type
    • Method Detail

      • getType

        public Class<T> getType()
        Get the type associated with this instance.
        Returns:
        configured type
      • buildAndBind

        public FieldBuilder<T> buildAndBind()
        Introspect for FieldBuilder annotations on getter methods of the configured class, and create and bind the corresponding fields.

        Note that non-static @ProvidesField annotations on instance methods are ignored, because there is no bean instance provided; use buildAndBind(Object) instead of this method to include them.

        Returns:
        this instance
      • buildAndBind

        public FieldBuilder<T> buildAndBind​(T bean)
        Introspect for FieldBuilder annotations on getter methods of the configured class, create and bind the corresponding fields, and set the given bean in the Binder.
        Parameters:
        bean - bean to introspect and bind
        Returns:
        this instance
        Throws:
        IllegalArgumentException - if bean is null
      • doBuildAndBind

        protected void doBuildAndBind​(T bean)
      • buildField

        protected HasValue<?> buildField​(Collection<? extends org.dellroad.stuff.vaadin8.FieldBuilder.AnnotationApplier<?>> appliers,
                                         String description)
        Instantiate and configure an HasValue according to the given scanned annotations.
        Parameters:
        appliers - annotation appliers
        description - description of the field (used for exception messages)
        Returns:
        new field
      • buildApplierList

        protected List<org.dellroad.stuff.vaadin8.FieldBuilder.AnnotationApplier<?>> buildApplierList​(Method method)
        Find all relevant annotations on the given method as well as on any supertype methods it overrides. The method must be a getter method taking no arguments. Annotations are ordered so that annotations on a method in type X appear before annotations on an overridden method in type Y, a supertype of X.
        Parameters:
        method - annotated getter method
        Returns:
        appliers for annotations found
        Throws:
        IllegalArgumentException - if method is null
        IllegalArgumentException - if method has parameters
      • buildDirectApplierList

        protected List<org.dellroad.stuff.vaadin8.FieldBuilder.AnnotationApplier<?>> buildDirectApplierList​(Method method)
        Find all relevant annotations declared directly on the given Method.
        Parameters:
        method - method to inspect
        Returns:
        annotations found
        Throws:
        IllegalArgumentException - if method is null
      • getAnnotationApplier

        protected <A extends Annotation> org.dellroad.stuff.vaadin8.FieldBuilder.AnnotationApplier<A> getAnnotationApplier​(Method method,
                                                                                                                           A annotation)
        Get the FieldBuilder.AnnotationApplier that applies the given annotation. Subclasses can add support for additional annotation types by overriding this method.
        Type Parameters:
        A - annotation type
        Parameters:
        method - method to inspect
        annotation - method annotation to inspect
        Returns:
        corresponding FieldBuilder.AnnotationApplier, or null if annotation is unknown