TextField Key Press Enter event

I have a view containing a TextArea, which when a user presses ‘Enter’ will submit the contents to the server.

My server is hosted in the US and European users see the Loading Indicator at the top of the screen as they type - which is not the best user experience.

I debugged using Chrome Dev Tools and on each key press, the client is sending a Sync RPC call to the server. The round-trip of each of these calls can be 300ms+ from Europe, resulting in the loading indicator.

These sync calls happen when using TextArea addKeyPressListener, addKeyUpListener and addKeyDownListener.

They do not happen when using Shortcuts.addShortcutListener( textArea, this::onSubmit, Key.ENTER ).listenOn( textField )

However, onSubmit then does not have the latest value of the TextArea, unless setValueChangeMode( ValueChangeMode.EAGER ) is set.

If this happens - every key press results in the sync event being sent to the server and the loading indicator issue.

I noted the MessageInput component has the desired behavior - no sync on key press, Enter submits the latest value. However, that component is not suitable for my requirements.

Looking at the Message Input source, it looks like this behavior is handled in JavaScript:

   this._textAreaController = new SlotController(this, 'textarea', 'vaadin-text-area', {
        initializer: (textarea) => {
          textarea.addEventListener('value-changed', (event) => {
            this.value = event.detail.value;
          });

          textarea.addEventListener('keydown', (event) => {
            if (event.key === 'Enter' && !event.shiftKey) {
              event.preventDefault();
              event.stopImmediatePropagation();
              this.__submit();
            }
          });

          textarea.minRows = 1;

          this._textArea = textarea;
        },
      });

Is there a way to achieve this desired behavior with TextArea (and TextField also, as this is used elsewhere in the application)

Background infos about the old value story: Synchronizing values along with a shortcutlistener · Issue #7046 · vaadin/flow · GitHub

Workaround: Shortcut listener on TextField sees old values · Issue #17484 · vaadin/flow · GitHub

Thank you!

It feels like this should be incorporated in an optional manner to the TextField / TextArea components.

You can sort of work around this with the Element API:

textArea.getElement().addEventListener("keypress", e -> {
    System.out.println("Enter pressed, value: " + textArea.getValue());
}).synchronizeProperty("value").setFilter("event.key === 'Enter'");

Setting the filter ensures the event is only sent when the Enter key is pressed, and synchronizing the value property, well also syncs the component value as part of that event. Compared to the workaround in the linked issue this avoids a second roundtrip that results from the executeJs call.

There is one downside here in that the keypress event is apparently fired before the text areas client-side value has been updated with the just entered character. However in your case that would be a newline due to the Enter key so that maybe acceptable. Also shouldn’t be an issue for text fields.

If you want to prevent adding the newline in general you can add addEventData("event.key === 'Enter' && event.preventDefault()") to the event registration.