Important Notice - Forums is archived
To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
Nested forms with custom fields
Hi,
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;
@PropertyId(SystemConfig.MAILER_SETTINGS)
private MailerSettingsField mailerSettingsField;
private Button saveButton;
@Autowired
public SystemSettingsView(SystemSettings systemSettings) {
this.systemSettings = systemSettings;
}
@Override
public void enter(ViewChangeEvent event) {
saveButton = new Button("Save", FontAwesome.SAVE);
saveButton.addClickListener(e -> save());
saveButton.setEnabled(false);
mailerSettingsField = new MailerSettingsField("Mailer Settings");
binder = new BeanFieldGroup<>(SystemConfig.class);
binder.bindMemberFields(this);
binder.setItemDataSource(systemSettings.getSystemConfig());
addComponent(new VerticalLayout(mailerSettingsField, saveButton));
}
private void save() {
mailerSetingsForm.commit();
}
}
public class MailerSettingsField extends CustomField<MailerSettings> {
@PropertyId(MailerSettings.MAILER_HOST)
private final TextField host = new TextField("Host");
@PropertyId(MailerSettings.MAILER_SENDER_NAME)
private final TextField senderName = new TextField("Sender Name");
@PropertyId(MailerSettings.MAILER_SENDER_ADDRESS)
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.setWidth("100%");
content.addComponents(host, senderName, senderAddress);
binder = new BeanFieldGroup<>(MailerSettings.class);
binder.bindMemberFields(this);
}
@Override
protected void setInternalValue(MailerSettings settings) {
super.setInternalValue(settings);
binder.setItemDataSource(settings);
}
@Override
protected Component initContent() {
return content;
}
@Override
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() {
binder.commit();
}
and to enable/disable the save-button, just use ValueChangeListeners on the textfields and the MailerSettingsField itself