]> source.dussan.org Git - vaadin-framework.git/commitdiff
Ensure value change happens before shortcuts in compatibility components (#11871)
authorAnna Koskinen <Ansku@users.noreply.github.com>
Wed, 15 Jan 2020 15:07:14 +0000 (17:07 +0200)
committerGitHub <noreply@github.com>
Wed, 15 Jan 2020 15:07:14 +0000 (17:07 +0200)
Fixes #10854

client/src/main/java/com/vaadin/client/ui/ShortcutActionHandler.java
uitest/src/main/java/com/vaadin/tests/components/datefield/CompatibilityDateFieldShortcut.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/datefield/CompatibilityDateFieldShortcutTest.java [new file with mode: 0644]

index 7499779352503b3724593bc5f74807c1101337bc..1c03a2719d35996b0bd33131d8d0578f10a6afec 100644 (file)
@@ -126,15 +126,31 @@ public class ShortcutActionHandler {
             target = Util.findPaintable(client, et);
         }
         final ComponentConnector finalTarget = target;
-
         event.preventDefault();
-
         /*
          * The focused component might have unpublished changes, try to
          * synchronize them before firing shortcut action.
          */
         client.flushActiveConnector();
-
+        /*
+         * Legacy components don't have built-in logic for flushing, they need a
+         * workaround with blur and focus to trigger the value change.
+         */
+        ComponentConnector activeConnector = getActiveConnector(client);
+        if (activeConnector != null) {
+            Class<?> clz = activeConnector.getClass();
+            while (clz != null) {
+                if (clz.getName().equals(
+                        "com.vaadin.v7.client.ui.AbstractLegacyComponentConnector")) {
+                    shakeTarget(et);
+                    Scheduler.get().scheduleDeferred(() -> {
+                        shakeTarget(et);
+                    });
+                    break;
+                }
+                clz = clz.getSuperclass();
+            }
+        }
         Scheduler.get().scheduleDeferred(() -> {
             if (finalTarget != null) {
                 client.updateVariable(paintableId, "actiontarget", finalTarget,
@@ -144,6 +160,26 @@ public class ShortcutActionHandler {
         });
     }
 
+    /**
+     * We try to fire value change in the component the key combination was
+     * typed. E.g. TextField may contain newly typed text that is expected to be
+     * sent to server before the shortcut action is triggered. This is done by
+     * removing focus and then returning it immediately back to target element.
+     * <p>
+     * This is a hack copied over from V7 in order to keep the compatibility
+     * classes working. Main V8 classes don't require shaking.
+     */
+    private static void shakeTarget(final Element e) {
+        blur(e);
+        focus(e);
+    }
+
+    private static native ComponentConnector getActiveConnector(
+            ApplicationConnection ac)
+    /*-{
+        return ac.@com.vaadin.client.ApplicationConnection::getActiveConnector()();
+    }-*/;
+
     private static native void blur(Element e)
     /*-{
         if (e.blur) {
diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/CompatibilityDateFieldShortcut.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/CompatibilityDateFieldShortcut.java
new file mode 100644 (file)
index 0000000..0881ced
--- /dev/null
@@ -0,0 +1,47 @@
+package com.vaadin.tests.components.datefield;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.vaadin.event.ShortcutAction.KeyCode;
+import com.vaadin.event.ShortcutListener;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Notification;
+import com.vaadin.v7.ui.DateField;
+
+@SuppressWarnings("deprecation")
+public class CompatibilityDateFieldShortcut extends AbstractTestUI {
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        String dateFormat = "dd/MM/yyyy";
+
+        DateField dateField = new DateField();
+        dateField.setValue(new Date(2018 - 1900, 0, 11));
+        dateField.setDateFormat(dateFormat);
+
+        dateField.addShortcutListener(
+                new ShortcutListener("Enter", KeyCode.ENTER, null) {
+                    @Override
+                    public void handleAction(Object sender, Object target) {
+                        SimpleDateFormat df = new SimpleDateFormat(dateFormat);
+                        Notification.show(df.format(dateField.getValue()));
+                    }
+                });
+
+        addComponent(dateField);
+    }
+
+    @Override
+    protected String getTestDescription() {
+        return "Modify the date manually (without using the popup element) and"
+                + " then press Enter. The notification should show the modified"
+                + " value instead of the old value.";
+    }
+
+    @Override
+    protected Integer getTicketNumber() {
+        return 10854;
+    }
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/datefield/CompatibilityDateFieldShortcutTest.java b/uitest/src/test/java/com/vaadin/tests/components/datefield/CompatibilityDateFieldShortcutTest.java
new file mode 100644 (file)
index 0000000..8ed2da2
--- /dev/null
@@ -0,0 +1,39 @@
+package com.vaadin.tests.components.datefield;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elements.DateFieldElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class CompatibilityDateFieldShortcutTest extends SingleBrowserTest {
+
+    private static final String DATEFIELD_VALUE_ORIGINAL = "11/01/2018";
+    private static final String DATEFIELD_VALUE_MODIFIED = "21/01/2018";
+
+    @Test
+    public void modifyValueAndPressEnter() {
+        openTestURL();
+
+        DateFieldElement dateField = $(DateFieldElement.class).first();
+        WebElement dateFieldText = dateField.findElement(By.tagName("input"));
+
+        assertEquals("DateField value should be \"" + DATEFIELD_VALUE_ORIGINAL
+                + "\"", DATEFIELD_VALUE_ORIGINAL, dateField.getValue());
+
+        dateFieldText.click();
+        dateFieldText.sendKeys(Keys.HOME, Keys.DELETE, "2");
+        dateFieldText.sendKeys(Keys.ENTER);
+
+        assertEquals("DateField value should be \"" + DATEFIELD_VALUE_MODIFIED
+                + "\"", DATEFIELD_VALUE_MODIFIED, dateField.getValue());
+
+        assertEquals(DATEFIELD_VALUE_MODIFIED,
+                $(NotificationElement.class).first().getCaption());
+    }
+}