0

In an application based on Vaadin 8 I want to implement a Command that remove the value of all fields. I have done this Using Binder. When user is activating the command a new Bean will be created.

    @Override public void menuSelected(MenuBar.MenuItem selectedItem) {

    controller.createNewBean();
    Page.getCurrent().reload();

}

I want to show a message box to the user which warns that by proceeding all values for all components will be lost. I am using a TabView and there are relatively many components.
I want to show this message only if user has changed a value for at least one component. I wonder if Vaadin has something like UI.getCurrent().isDirty() or another mechanism to determine if user has entered a new value to a component?

Thanks for help

Govan
  • 2,079
  • 4
  • 31
  • 53

2 Answers2

1

The most effective way that I found was to register a new listener to the binder to get notified of any changes in the component value.

In this listener, I use an atomic integer that gets incremented for every change. Later on, using this atomic integer, I decide if any of the fields have been touched by the user.

Not that, this does not detect changes but it detects the modifications (e.g. the user might change a field value multiple times but set the value to the original value finally).

AtomicInteger counter = new AtomicInteger();
binder.addValueChangeListener((HasValue.ValueChangeListener<Object>) event -> counter.incrementAndGet());

Make sure to reset the counter when required (e.g. at the save time).

Youness
  • 1,920
  • 22
  • 28
  • Elegant solution! With Vaadin 14.1.23 the generics part is slightly different (at least from what my Eclipse accepts): binder.addValueChangeListener((HasValue.ValueChangeListener super ValueChangeEvent>>) event -> counter.incrementAndGet()); – S. Doe Apr 05 '20 at 06:47
0

You may want to use binder.hasChanges(). This basically checks whether your fields and the underlying bean bound to the fields differ because of user interactions.

From Vaadin's Docs:

Check whether any of the bound fields' values have changed since last explicit call to setBean(Object), readBean(Object), removeBean(), writeBean(Object) or writeBeanIfValid(Object).

See Vaadin's API and Vaadin Doc's chapter Binding Data to Forms for more information.

With Page.getCurrent().reload() you get a new UI and all your components are reset as if you opened a new tab. For resetting your components I would recommend to use binder.readBean(theNewBeanWithFreshValues). This sets the values of the bound fields back to the values of the bean.

Axel Meier
  • 1,105
  • 2
  • 18
  • 28
  • Thanks @Axel Meier. It seems the only way is binder.hasChanges(). The problem is that I have different Beans and different tabs and I have to be aware of many binders. I am using reload instead of readBrean because of this as well. – Govan Jun 14 '17 at 05:27
  • 1
    I tested implementation with binder hasChanges. It is not working as described in the documentation. See this: https://vaadin.com/forum/#!/thread/14906891/15007809 – Govan Jun 14 '17 at 06:25
  • @Govan Thank you for your feedback. Indeed `hasChanges()` makes more sense to use in combination with `readBean()` and `writeBean()`. With `setBean()` the changes are automatically committed `hasChanges()` would return false. Also with `setBean()` there is no way to restore the old values anymore. – Axel Meier Jun 14 '17 at 08:17