Async Bug: ValueChangeListener gets event from client without user entering anything

That way of setting value probably will not work, if the future is run before component is attached. Why you need to do it this way?

This breaks my forms, because they mark fields that have been edited by the user as “modified” which is triggered incorrectly here

If you use Binder, it has hasChanges method to check if bound fields have changes

@yummy-rhino

That way of setting value probably will not work, if the future is run before component is attached
I don’t think that’s true, you can call setValue before the components are attached? Even in the constructor is before it’s attached

I just tried

        var ui = UI.getCurrent();
        field.addAttachListener(event -> {
            f = CompletableFuture.runAsync(() -> {
                ui.accessSynchronously(() -> {
                    field.setValue("asd");
                });
            });
        });

same bug

I can’t use Binders, my fields have advanced behavior that cannot be implemented using binders.
Binders only allow two states, one which is the resettable state, and one that is the currently entered state. I have a third state with a suggested value, when the suggested value is applied, the field also has a different background color (yellow)

and if the user modifies the field it’s marked blue

At all times the user is allowed to reset the field to either the suggested or original state

And the suggested fields need to do some computation in the background when the user enters values, so I want to do them asynchronously

That’s theoretically possible with custom error level of the binder, I’ve done something similar but with “info / blue”

Honestly I think it’s simpler to just store three copies of my objects (original+edited+suggestions) and do the processing and binding to the fields myself

i have my own property system at this point anyway, trying to hack on top of binders just feels like more complication. And I’m not even sure if I could get it to store, apply and restore a third state conditionally at all.

@observant-okapi so you programmatically set initial values and want the background color to be changed when user touches the value. I would do that by adding event listener via JavaScript. That way you wont need any kinky tweaking in your serverside Java code.

TextField textField = new TextField("Field"); textField.setValue("Value"); textField.getElement().executeJs( "this.inputElement.addEventListener('change', (e) => this.setAttribute('touched',true));");

Like above, and then adding the following in my styles

vaadin-text-field:not([touched])::part(input-field) { background: yellow; }

With above code my text field will have yellow background until I change its value first time

I still need to recompute the suggested values on the serverside if the user makes a change

if i do that asynchronously on the server, it goes into a infinite loop

because the server itself generates “client” change events which then trigger another suggestion recomputation etc