Nested forms with custom fields


i am having a hard time getting to grips with data binding when building forms with custom fields.

I have a custom field (MailerSettingsField) which has three textfiles, bound to my Model.
This custom field is used as a part of a larger form, which at some point should contain a number of other, similar custom fields.

The text fields display the correct values.

Now i want to be able to do three things:

  1. When clicking the save button, the values from the text fields should be applied to the model.
  2. I want to be notified of changes to any text field, so that i can enable the save button.
  3. I want to be able to ask the custom field, whether it is modified.

Calling mailerSetingsField.commit() has no effect.
Calling mailerSettingsField.isModified() always returns false

I could overwrite commit() and isModified() of my custom field to achieve this, but i don’t think that’s the best way to go.

How can i achieve my goals?

public class SystemSettingsView extends VerticalLayout implements View {

    private final SystemSettings systemSettings;

    private BeanFieldGroup<SystemConfig> binder;

    private MailerSettingsField mailerSettingsField;

    private Button saveButton;

    public SystemSettingsView(SystemSettings systemSettings) {
        this.systemSettings = systemSettings;

    public void enter(ViewChangeEvent event) {
        saveButton = new Button("Save", FontAwesome.SAVE);
        saveButton.addClickListener(e -> save());

        mailerSettingsField = new MailerSettingsField("Mailer Settings");

        binder = new BeanFieldGroup<>(SystemConfig.class);

        addComponent(new VerticalLayout(mailerSettingsField, saveButton));

    private void save() {

public class MailerSettingsField extends CustomField<MailerSettings> {

    private final TextField host = new TextField("Host");

    private final TextField senderName = new TextField("Sender Name");

    private final TextField senderAddress = new TextField("Sender Address");

    private final FormLayout content;
    private final BeanFieldGroup<MailerSettings> binder;

    public MailerSettingsField(String caption) {
        Label label = new Label(caption);

        content = new FormLayout(label);

        content.addComponents(host, senderName, senderAddress);

        binder = new BeanFieldGroup<>(MailerSettings.class);

    protected void setInternalValue(MailerSettings settings) {

    protected Component initContent() {
        return content;

    public Class<MailerSettings> getType() {
        return MailerSettings.class;

I did not try your code, but i think the problem is, that you don’t commit the field-group of MailerSettingsField.
So you can set binder.setBuffered(false) (what i would recommend) or you can overwrite the commit-function of MailerSettingsField:

public void commit() {

and to enable/disable the save-button, just use ValueChangeListeners on the textfields and the MailerSettingsField itself