Vaadin 8 - binder.addStatusChangeListener

Hi everyone,

I’m trying Vaadin 8 beta1 and I’m trying to create an AbstractForm class (like viritin’s AbstractForm).
I read the documentation (here https://github.com/vaadin/framework/blob/master/documentation/datamodel/datamodel-forms.asciidoc )
Especially these lines:

Binder keeps track of which bindings have been updated by the user and which bindings are in an invalid state. It also fires an event when this status changes. We can use that event to make the save and reset buttons of our forms become enabled or disabled depending on the current status of the form.

binder.addStatusChangeListener(event -> {
  boolean isValid = !event.hasValidationErrors();
  boolean hasChanges = binder.hasChanges();
  saveButton.setEnabled(hasChanges && isValid);
  resetButton.setEnable(hasChanges);
});

So I try to create a form with save button.

public class SaisieView extends VerticalLayout  implements IView, Serializable  {
    private static final long serialVersionUID = -1555973233679064001L;
    public static final String VIEW_NAME = "entry";

    Binder<Person> b;
    
    private Button saveButton = new Button("save");
    private TextField name  = new TextField("name");
    private TextField firstName = new TextField("firstName");
    
    
    @PostConstruct
    void createContent() {
        FormLayout layout = new FormLayout();
        layout.addComponents(name, firstName, saveButton);
        addComponent(layout);
    }
    @Override
    public void enter(ViewChangeListener.ViewChangeEvent viewEvent) {
        b = new Binder<Person>();
        b.forField(name).asRequired("required name").bind(Person::getName, Person::setName);
        b.forField(firstName).asRequired("required firstname").bind(Person::getFirstname, Person::setFirstname);
        Person person= new Person();
        person.setName("name");
        person.setFirstname("firstname");
        b.addStatusChangeListener(event -> {
              boolean isValid = !event.hasValidationErrors();
              boolean hasChanges = b.hasChanges();
              saveButton.setEnabled(isValid);
            });
        b.readBean(person);
        
    }
    
    public class Person {
        private String name;
        private String firstname;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getFirstname() {
            return firstname;
        }
        public void setFirstname(String firstname) {
            this.firstname = firstname;
        }
        
    }
    
}
  • When I clear manually namefield → Save is disabled (perfect)
  • Then I clear firstnamefield → Save is disabled (perfect)
    Then I fill firstnamefield → Save is enabled
    boolean isValid = !event.hasValidationErrors(); → return true (ad it should be false if i understand it correctly)

Is there a bug or I don’t understand something ?

Thanks,

Hi!

When no bean is set to the Binder it will only run validation on the field that has changed. In your code example instead of calling readBean on line 31 you could set the bean to the binder by calling setBean, after which the whole bean will be validated after changes to any field.

Same here: https://vaadin.com/forum#!/thread/14852578

I will try setBean.

Sorry i didn’t find your post but it’s the same problem.
I changed readBean to setBean and I’ve got the same behaviour.
I also try with Binder and BeanBinder (same behaviour).

So then it is official it is bug. Because last time i try to debug it i found that only current field fires the status change event.

You can “hack” it when you get validationErrors from binder and not from event - but if i remeber correctly there was another issue (while initialization process or binding or something else).

For now, I removed the addStatusChangeListener so save button is always enabled.
So the user can click on “Save” button, the binder validates bean (writeBean) and I get the errors.

I don’t know how to get the validation errors from the binder (without calling validate, because “validate” function can’t be called in addStatusChangeListener ).

There is a pull request here https://github.com/vaadin/framework/pull/8274
(This patch also clarifies the javadocs of StatusChangeEvents’hasValidationErrors.)
So I think my problem will be solved in the next version.