Flow: Class component.Key is practically unsable with KeyDownEvent

Created on 19 Sep 2018  路  6Comments  路  Source: vaadin/flow

Goal: Submit form when Enter key is pressed Or Call a method when Enter key is pressed

Code with comments that explain the insanity:

password.addKeyDownListener(new ComponentEventListener<KeyDownEvent>() {

    @Override
    public void onComponentEvent(KeyDownEvent event) {
        if(event.getKey().equals(Key.ENTER)) //equals not implemented, doesnt work
            pressed();
        if(event.getKey().matches(Key.ENTER.toString())) //toString not implemented, doesnt work
            pressed();
        if(event.getKey().getKeys().containsAll(Key.ENTER.getKeys())) //works but come on this is stupid
            pressed();

    }
});

Key class is not actually a Key class, its Keys class because it contains multiple Keys inside of itself. I can understand the need for this when pressing down multiple keys eg. "ctrl+enter" but I dont think this is the way to do it.
Key need implement equals and toString. Key.Enter.equals(Key.Enter) makes sense.

question

Most helpful comment

I see. I just feel like the interface is unintuitive. Being unable to compare one key to another easily.
Enter key is the only key I've needed to listen so far and I don't see myself needing to capture a broader set of keys in the future.

I think the use case is when a user wants to manually check what key was pressed. I guess the issue then comes down to "When would someone want to do this?" but I don't know. Other than the inability to use this password.addKeyDownListener(Key.ENTER, event -> pressed());

All 6 comments

I don't fully understand what you are describing, but you can use addKeyDownListener(Key key, ComponentEventListener<KeyDownEvent> listener) to specify the key without checking it yourself, e.g.

password.addKeyDownListener(Key.ENTER, event -> pressed());

Methods equals and toString are not implemented because Key is a functional interface, backed by a list of strings which are all the possibile denominations of that key in different browsers. If you look at the JavaDocs and source code, you'll find also a matches(String key) method you can use as a shortcut to check if the Key instance matches a certain key denomination.

My bad, I didn't see the modifiers were an optional parameter. This solves my main issue.

This does not however solve the issue that matches(String key) method is cumbersome to use since you cannot ask Key for its String representation. If one wishes to use matches(String key) one needs to write key.matches("Enter") instead of key.matches(Key.Enter) or key.matches(Key.Enter.toString()) and hope that Enter key definition never changes from "Enter" to for example "ENTER"

The matches method is intended to match strings coming from the browser, that's why it accepts a string. An overload of the method accepting another Key could be a shortcut, but do you feel there are real use cases where to use that?

I see. I just feel like the interface is unintuitive. Being unable to compare one key to another easily.
Enter key is the only key I've needed to listen so far and I don't see myself needing to capture a broader set of keys in the future.

I think the use case is when a user wants to manually check what key was pressed. I guess the issue then comes down to "When would someone want to do this?" but I don't know. Other than the inability to use this password.addKeyDownListener(Key.ENTER, event -> pressed());

I agree with @Bloodust :

  1. the API is counter-intuitive and feels obfuscated (I'd expect an Enum constant since a set of keys is usually a finite set), definitely not a closure.
  2. The API is hard to use (it's really to write a code for "the key I received, is it an Enter key?"). I should be able to use event.code == Key.Enter instead of event.code.matches("Enter"). The API basically leaks the uncertainty of JavaScript of having multiple key codes for the same key.
  3. The performance suffers because of that: addKeyDownListener() should take advantage of DomListenerRegistration.filter() so that the keys are filtered client-side; instead all key strokes are sent to the server and are filtered server-side.

This API is completely broken by design. There's even ShortcutRegistration.HashableKey class to work around the broken equals()/hashCode()....... wat

It would be helpful if you at least provide convenient checker methods in Key and KeyModifier that allow me to verify that a specific Key and a specific KeyModifier were pressed as indicated by the key event listener methods.

For instance, something like:

  private boolean isKeyPressed(final KeyDownEvent event, final Key triggerKey, final KeyModifier triggerKeyModifier) {
    return triggerKey.getKeys().equals(event.getKey().getKeys()) && event.getModifiers().stream()
      .allMatch(kms -> kms.getKeys().stream().allMatch(km -> triggerKeyModifier.getKeys().contains(km)));
  }
Was this page helpful?
0 / 5 - 0 ratings

Related issues

Artur- picture Artur-  路  4Comments

pleku picture pleku  路  4Comments

knoobie picture knoobie  路  4Comments

pleku picture pleku  路  4Comments

vlukashov picture vlukashov  路  3Comments