ObjectProperty in Vaadin Flow

It seems that there is no equivalent in Vaadin Flow for the old ObjectProperty and other change listening data classes.

Particularly, I’ve tried to port my example [here]
(http://razvanml.github.io/reco-link/2016-12-05/Vaadin-Temperature-Conversion/) to Flow.
It is a temperature conversion toy example, where the temperature is stored as a single value. This value is presented in TextField as a specific temperature scale by using converters and it allows the update back by implementing the same converters in reverse direction. When a field changes a value, all the other fields receive the change notification, courtesy of ObjectProperty implementation.

I’m wondering what is the approach for this application using Flow. From what I’ve read, Binder is the option. Using a binder would require to store N values, one for each temperature scale and upon change, manually decide which of the N-1 fields has to update. Is this the only viable option?

Thanks,
Razvan

Still, no answer? Would it make sense writing the document / change observers for common controls like table, drop down combo or text field? Interesting that nobody sticking to MVC approach has reported this before. Are we a dying species?

Vaadin Flow has the Binder concept and it is easy to do things like that once you get the hang of it. For example, your temperature converter can be created somewhat like below:

    public class TemperatureForm extends FormLayout {

        private static final String errorMessage = "Must be a number";
        private TextField degree = new TextField("Degree"), kelvin = new TextField("Kelvin");
        private Binder<Temperature> binder = new Binder<>();
        private Temperature temperature = new Temperature(24);

        public TemperatureForm() {
            add(degree, kelvin);
            binder.forField(degree).withConverter(new StringToDoubleConverter(errorMessage)).bind(Temperature::getDegree, Temperature::setDegree);
            binder.forField(kelvin).withConverter(new StringToDoubleConverter(errorMessage)).bind(Temperature::getKelvin, Temperature::setKelvin);
            reload();
            degree.addValueChangeListener(e -> reload());
            kelvin.addValueChangeListener(e -> reload());
        }

        private void reload() {
            binder.setBean(temperature);
        }
    }

    public class Temperature {

        private double degree;

        public Temperature(double degree) {
            this.degree = degree;
        }

        public void setDegree(double degree) {
            this.degree = degree;
        }

        public double getDegree() {
            return degree;
        }

        public void setKelvin(double kelvin) {
            this.degree = kelvin - 273.15;
        }

        public double getKelvin() {
            return degree + 273.15;
        }
    }

The code below is slightly more efficient because the reload method doesn’t set the bean again each time a value is changed.

    public class TemperatureForm extends FormLayout {

        private StringToDoubleConverter converter = new StringToDoubleConverter("Must be a number");
        private Binder<Temperature> binder = new Binder<>();
        private Temperature temperature = new Temperature(24);

        public TemperatureForm() {
            add(createField("Degree", Temperature::getDegree, Temperature::setDegree), createField("Kelvin", Temperature::getKelvin, Temperature::setKelvin));
            binder.setBean(temperature);
        }

        private void reload() {
            binder.readBean(temperature);
        }

        private TextField createField(String label, ValueProvider<Temperature, Double> getter, Setter<Temperature, Double> setter) {
            TextField textField = new TextField(label);
            binder.forField(textField).withConverter(converter).bind(getter, setter);
            textField.addValueChangeListener(e -> reload());
            return textField;
        }
    }