Browse Source

Ensure value change happens before shortcuts in compatibility components (#11871)

Fixes #10854
tags/8.10.0.beta1
Anna Koskinen 4 years ago
parent
commit
2bf0b02220
No account linked to committer's email address

+ 39
- 3
client/src/main/java/com/vaadin/client/ui/ShortcutActionHandler.java View 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) {

+ 47
- 0
uitest/src/main/java/com/vaadin/tests/components/datefield/CompatibilityDateFieldShortcut.java View File

@@ -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;
}
}

+ 39
- 0
uitest/src/test/java/com/vaadin/tests/components/datefield/CompatibilityDateFieldShortcutTest.java View File

@@ -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());
}
}

Loading…
Cancel
Save