Binder fields sync

Hi, I am working on more complex forms now with ValidationBinder and I ran into the issue that user input changes to field are not propagated to other readOnly bound to the same property.
Checked out the clean “base-starter-gradle-24” to test out if there is something with my setup and could not get it working there as well. (screenshot attached)

Handlers are being called if bean is being set but not when input has changed and values were written to the bean.

Is this expected behaviour?
Does not make sense to me since I would expect that readOnly fields state would be always kept in sync with bean.

I could not find any reference in documentation aside “Data Binding” FAQ and delving into source did not yield anything :frowning_with_open_mouth:

Thanks in advance for any help with this
image.png

This is the expected behavior, as fields are not connected to each other and there’s nothing that reacts on changes on the bean properties.

You can do it by yourself by taking the references of the readonly bindings and force a read when the editable field changes its value

Binder<PojoBean> binder = new Binder<>(PojoBean.class);

PojoBean bean = new PojoBean();
binder.setBean(bean);

TextField textField = new TextField("Your name");
binder.forField(textField).bind(PojoBean::getText, PojoBean::setText);

TextField textField2 = new TextField("Your name");
Binder.Binding<PojoBean, String> binding = binder.bindReadOnly(textField2, PojoBean::getText);

  textField.addValueChangeListener(ev -> {
      binding.read(bean);
  });

Thank you for the response
I was afraid that it will be “expected”. Saw these around on stack overflow but for me it it feels like the hackaround:

  1. This would cause performance issue, especially in larger forms as it will force rerender of entire form (how many bean.read cascade there could be)
  2. It almost kills the point of having binding for field at all since we might have as well imperatively set in addValueChangeListener, as I think the external bean changes would trigger it on text field as well

Since we are on topic I would also like to give my general feedback
Sadly, the state management part of Vaadin was the most underwhelming part of using the framework so far.
Only available tool is Binder but it is lacking in many areas as well. Having experience in both Android and React, level of “imperativity” of code required for mundane tasks feels like being sent back to JQuery’s era sprawling reference jungles :smiling_face_with_tear:

It is especially odd to me since I feel like reactive way of state management has proven over time as the most readable and scalable and there is a number of solid implementations (e.g. Android Jetpack’s ViewModel)

During my search for the issue I’ve encountered long standing epic and discussion and dropped my +1 there
https://github.com/vaadin/flow/issues/3801

Feedback is always appreciated

  1. This would cause performance issue, especially in larger forms as it will force rerender of entire form (how many bean.read cascade there could be)

May I ask the use case for binding the same properties to multiple fields? Or is the point about having a reactive model where a change on a bean field triggers changes on other fields?

  1. It almost kills the point of having binding for field at all since we might have as well imperatively set in addValueChangeListener, as I think the external bean changes would trigger it on text field as well
    Changes on the bean are not reflected on the fields automatically. If the bean properties are updated programmatically, you need to call readBean or setBean to inform binder, and thus the bound fields, of the external change

mmm, there are a few cases I am doing

  • some dynamicity for field’s properties (e.g. disabled/enabled based on value from other field)
  • fetching and displaying additional context based on value change (more complex ReadOnlyHasValue component)

attached image very concrete example of dynamic form section that depends on selected option (guess it is also a variant of second case) and instead of just using simple bindRead I have to make my own bootleg readonly binder :persevere:
I guess the same could be done directly in addValueChangeListener for radio button group but I was not sure if this will catch changes that are coming from external bean changes (e,g. form reinitialised with different bean)

I am also using Kotlin and Karibu, which compresses and makes layout much more declarative, so colocation of read bindings with component it affects is another step in making code expressive and comprehensive.
image.png

Thanks again for your feedback!

If you have complex forms or let me call them subforms depending on other fields… it’s often easier to split up your DTO and form into smaller pieces and reuse / re-render only those and removed the need for the binder’s value change listener which is called on any value change

Well, this rules subsection is in fact that kind of a split form with separate binder. There still will be some friction when you can’t freely act onto all changes in the binder.

My point being is that when binder is in play, from my understanding it was a tool that allows you to get into “UI as state of the data” instead of imperative JQuerying (and I guess it was created because imperative forms are a nightmare)
So whenever you have to cross the boundaries from reactive to imperative it generates boilerplate.

It also might very well be that mind has been thoroughly deformed by years of React development :upside_down_face:

Probably the latter :sweat_smile: I feel the same about React’s approach - but still interesting to see other approaches to the see good and bad sides of the things you are currently using

@quirky-zebra just out of curiosity
how would you implement “when these 2 fields are non-null and of specific predefined value, display me this piece of HTML”

I am struggling to find some compact and easily readable way to do it imperatively but it is absolutely trivial in any reactive paradigm

I would add a value change listener to both fields; that know each other or the bean and add/remove the html

I guess issue I see with this approach is that there is plenty of edge cases (e.g. full bean reload fills fields sequentially) so it would cause extra rerenders.
Oh well, suppose we can afford it since it runs on server

Thanks for responsing and hope you having a nice day!

okay, here is another sample
dynamically set fields requiredness

in this case,
setting own field’s property is trivial but
I am blocked since I can’t dig out binding for other field since getBinding only supports propertyName as param
so I need to create higher scope variable to hold it, guess I can get field from binding so I should use those instead

sorry for spamming, just venting I guess :triumph:
image.png

final result

to say that I am not proud of that one would be a tremendous understatement
image.png

I can’t really speak for kotlin, but if I remember correctly it’s possible to “toggle” the required state or overload the asRequired with a custom validation that allow to access anything you need