Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vaadin 8: order in which change and binder listeners are called gets messed up #9917

Closed
sergetania opened this issue Aug 31, 2017 · 1 comment
Labels

Comments

@sergetania
Copy link

A field is bound to a bean property using Binder. The same field also has a valueChangeListener. In the code below, when the value of the combobox changes the value change listener is invoked before the setter on the Data object. It is wrong. However, if the lines of code that registers the listener and the setBean call are reversed the setter on the Data object will be called before the listener (correct behavior)

In this version of the code, the listener method ic invoked before the setValue method:

public class ValueChangeView extends VerticalLayout implements View {
  public class Data {
    private String value;
    public String getValue() {
      return value;
    }
    public void setValue(String value) {
      this.value = value;
    }
  }
  private Data data;
 
  @Override
  public void enter(ViewChangeEvent event) {
    data = new Data();
    Binder<Data> binder = new Binder<>(Data.class);
    NativeSelect<String> combo = new NativeSelect<>("Select");
    String items = { "One", "Two" };
    combo.setItems(items);
    addComponent(combo);
    Label comboValue = new Label();
    addComponent(comboValue);
    binder.forField(combo).bind("value");

    combo.addValueChangeListener(e -> comboValue.setValue(data.getValue()));

    binder.setBean(data);
  }
}

In the following version, the setValue method is called before the listener:

public void enter(ViewChangeEvent event) {
  data = new Data();
  Binder<Data> binder = new Binder<>(Data.class);
  NativeSelect<String> combo = new NativeSelect<>("Select");
  String items = { "One", "Two" };
  combo.setItems(items);
  addComponent(combo);
  Label comboValue = new Label();
  addComponent(comboValue);
  binder.forField(combo).bind("value");
 
  binder.setBean(data);
 
  combo.addValueChangeListener(e -> comboValue.setValue(data.getValue()));
}

This happens because of the following code in the Binder class called during the setBean call. The listener associated with the binder is removed from the list and then added. However, if there is another listener in the list (the added value change listener) the order is reversed and the user defined listener is called before the binder's listener.

private void initFieldValue(BEAN bean) {
  assert bean != null;
  assert onValueChange != null;
  onValueChange.remove();
  try {
    getField().setValue(convertDataToFieldType(bean));
  } finally {
    onValueChange = getField() .addValueChangeListener(this::handleFieldValueChange);
  }
}

The order may also get messed up during other binder calls as well. The problem is the list of listeners in the EventRouter does not maintain order of methods. It gets messed up and, as a result bean values may be updated either before or after other listeners are invoked. It's inconsistent and unpredictable.

To see this in the attached project navigate to
https://localhost:8080/v8-nativeselect/#!Change

v8-errors.zip

@stale
Copy link

stale bot commented Mar 19, 2018

Hello there!

It looks like this issue hasn't progressed lately. There are so many issues that we just can't deal them all within a reasonable timeframe.

There are a couple of things you could help to get things rolling on this issue (this is an automated message, so expect that some of these are already in use):

  • Check if the issue is still valid for the latest version. There are dozens of duplicates in our issue tracker, so it is possible that the issue is already tackled. If it appears to be fixed, close the issue, otherwise report to the issue that it is still valid.
  • Provide more details how to reproduce the issue.
  • Explain why it is important to get this issue fixed and politely draw others attention to it e.g. via the forum or social media.
  • Add a reduced test case about the issue, so it is easier for somebody to start working on a solution.
  • Try fixing the issue yourself and create a pull request that contains the test case and/or a fix for it. Handling the pull requests is the top priority for the core team.
  • If the issue is clearly a bug, use the Warranty in your Vaadin subscription to raise its priority.

Thanks again for your contributions! Even though we haven't been able to get this issue fixed, we hope you to report your findings and enhancement ideas in the future too!

@stale stale bot added the Stale Stale bot label label Mar 19, 2018
@TatuLund TatuLund added the BFP label Mar 23, 2018
@stale stale bot removed the Stale Stale bot label label Mar 23, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants