vaadin / flow

Vaadin Flow is a Java framework binding Vaadin web components to Java. This is part of Vaadin 10+.
Apache License 2.0
598 stars 165 forks source link

Value change listener with ValueChangeMode.TIMEOUT not working #18970

Open scrmtrey91 opened 6 months ago

scrmtrey91 commented 6 months ago

Description

We are using ValueChangeMode.TIMEOUT on fields (text field etc) with 3500 timeout.

However it is not working as it should.

Sometimes it calls listener on the first character and also when using backspace to delete in it. Then magically working for every other characters until it does not.

We upgraded from vaadin 8 and not this is not working properly. (like many other things reported already)

Expected outcome

When value change it should wait timeout amount before calling value change listener.

Not before timeout and not after timeout, but aprox on timeout (+/- 100ms).

Also should be consistent.

Minimal reproducible example

TextField textField = new TextField();
                    textField.setValueChangeTimeout(3500);
                    textField.setValueChangeMode(ValueChangeMode.TIMEOUT);

                    textField.addValueChangeListener(event -> {
                        if (event.isFromClient()) {
                            Notification.show("blabla");
                        }
                    });

Steps to reproduce

  1. Add textfield above to view
  2. Click into textfield and type characrted
  3. Value change istener run immediately not after TIMEOUT

Environment

Vaadin version(s): latest 23 or latest 24 Browser: Edge, Chrome..it does not matter

Browsers

Issue is not browser related

web-padawan commented 5 months ago

The issue is not specific to TextField but can be also reproduced with Input from Flow html components:

public class ValueChangeModeTimeoutPage extends Div {

    public ValueChangeModeTimeoutPage() {
        Div log = new Div();

        Input input = new Input();
        input.setValueChangeTimeout(3500);
        input.setValueChangeMode(ValueChangeMode.TIMEOUT);

        input.addValueChangeListener(event -> {
            if (event.isFromClient()) {
               log.add(new Div(event.getValue()));
            }
        });

        add(input, log);
    }
}

To me it seems like a result of using registration.throttle() for ValueChangeMode.TIMEOUT - see this logic. Based on https://github.com/vaadin/flow/pull/4945 where this mode was added, I think the current behavior is kind of as expected:

Syncs the value at defined intervals as long as the value changes from one event to the next.

As a workaround, consider using ValueChangeMode.LAZY which uses debounce() instead of throttle().

sissbruecker commented 5 months ago

Moving this over to the Flow repo as it doesn't seem to be a component-specific issue.