Composite Fields with CustomField

The CustomField is a way to create composite components as with CustomComponent, except that it implements the Field interface and inherits AbstractField, described in "Field Components". A field allows editing a property value in the Vaadin data model, and can be bound to data with field groups, as described in "Creating Forms by Binding Fields to Items". The field values are buffered and can be validated with validators.

A composite field class must implement the getType() and initContent() methods. The latter should return the content composite of the field. It is typically a layout component, but can be any component.

It is also possible to override validate(), setInternalValue(), commit(), setPropertyDataSource, isEmpty() and other methods to implement different functionalities in the field. Methods overriding setInternalValue() should call the superclass method.

Basic Use

Let us consider a simple custom switch button component that allows you to click a button to switch it "on" and "off", as illustrated in A custom switch button field.

A custom switch button field

The field has Boolean value type, which the getType() returns. In initContent(), we initialize the button and the layout. Notice how we handle user interaction with the button to change the field value. We customize the setValue() method to reflect the state back to the user.

public class BooleanField extends CustomField<Boolean> {
    Button button = new Button();

    public BooleanField() {
        setValue(true); // On by default
    }

    @Override
    protected Component initContent() {
        // Flip the field value on click
        button.addClickListener(click ->
            setValue(! (Boolean) getValue()));

        return new VerticalLayout(
            new Label("Click the button"), button);
    }

    @Override
    public Class<Boolean> getType() {
        return Boolean.class;
    }

    @Override
    public void setValue(Boolean newFieldValue)
        throws com.vaadin.data.Property.ReadOnlyException,
        ConversionException {
        button.setCaption(newFieldValue? "On" : "Off");
        super.setValue(newFieldValue);
    }
}

We can now use the field in all the normal ways for a field:

// Create it
BooleanField field = new BooleanField();

// It's a field so we can set its value
field.setValue(new Boolean(true));

// ...and read the value
Label value = new Label(field.getValue()?
    "Initially on" : "Initially off");

// ...and handle value changes
field.addValueChangeListener(event ->
    value.setValue(field.getValue()?
        "It's now on" : "It's now off"));