summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java4
-rw-r--r--client/src/main/java/com/vaadin/client/ui/VDateField.java20
-rw-r--r--server/src/main/java/com/vaadin/ui/AbstractDateField.java10
-rw-r--r--shared/src/main/java/com/vaadin/shared/ui/datefield/AbstractDateFieldServerRpc.java22
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/datefield/DateTimeFieldEventOrder.java54
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/datefield/DateTimeFieldEventOrderTest.java39
6 files changed, 149 insertions, 0 deletions
diff --git a/client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java b/client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java
index 2682973964..a199e2cd4a 100644
--- a/client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java
+++ b/client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java
@@ -496,6 +496,10 @@ public abstract class VAbstractPopupCalendar<PANEL extends VAbstractCalendarPane
setText(previousValue);
}
updateTextFieldEnabled();
+ bufferedDateString = text.getText();
+ updateBufferedResolutions();
+ // send the Time changes with delayed rpc.
+ sendBufferedValuesWithDelay();
}
/**
diff --git a/client/src/main/java/com/vaadin/client/ui/VDateField.java b/client/src/main/java/com/vaadin/client/ui/VDateField.java
index 2d4136bd76..a6c5a158de 100644
--- a/client/src/main/java/com/vaadin/client/ui/VDateField.java
+++ b/client/src/main/java/com/vaadin/client/ui/VDateField.java
@@ -291,6 +291,26 @@ public abstract class VDateField<R extends Enum<R>> extends FlowPanel
}
/**
+ * Puts the {@link #bufferedDateString} and {@link #bufferedResolutions}
+ * changes into the rpc queue and clears their values.
+ * <p>
+ * Note: The value will not be sent to the server immediately. It will be
+ * sent when a non {@link com.vaadin.shared.annotations.Delayed} annotated
+ * rpc is triggered.
+ * </p>
+ *
+ * @since
+ */
+ public void sendBufferedValuesWithDelay() {
+ rpc.updateValueWithDelay(bufferedDateString,
+ bufferedResolutions.entrySet().stream().collect(
+ Collectors.toMap(entry -> entry.getKey().name(),
+ entry -> entry.getValue())));
+ bufferedDateString = null;
+ bufferedResolutions.clear();
+ }
+
+ /**
* Returns all available resolutions for the field in the ascending order
* (which is the same as order of enumeration ordinals).
* <p>
diff --git a/server/src/main/java/com/vaadin/ui/AbstractDateField.java b/server/src/main/java/com/vaadin/ui/AbstractDateField.java
index f03c900b97..f7a085bc0d 100644
--- a/server/src/main/java/com/vaadin/ui/AbstractDateField.java
+++ b/server/src/main/java/com/vaadin/ui/AbstractDateField.java
@@ -88,6 +88,16 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster &
@Override
public void update(String newDateString,
Map<String, Integer> resolutions) {
+ valueUpdate(newDateString, resolutions);
+ }
+
+ @Override
+ public void updateValueWithDelay(String newDateString,
+ Map<String, Integer> resolutions) {
+ valueUpdate(newDateString, resolutions);
+ }
+
+ private void valueUpdate(String newDateString, Map<String, Integer> resolutions) {
Set<String> resolutionNames = getResolutions().map(Enum::name)
.collect(Collectors.toSet());
resolutionNames.retainAll(resolutions.keySet());
diff --git a/shared/src/main/java/com/vaadin/shared/ui/datefield/AbstractDateFieldServerRpc.java b/shared/src/main/java/com/vaadin/shared/ui/datefield/AbstractDateFieldServerRpc.java
index e82c45f171..0344110443 100644
--- a/shared/src/main/java/com/vaadin/shared/ui/datefield/AbstractDateFieldServerRpc.java
+++ b/shared/src/main/java/com/vaadin/shared/ui/datefield/AbstractDateFieldServerRpc.java
@@ -17,6 +17,7 @@ package com.vaadin.shared.ui.datefield;
import java.util.Map;
+import com.vaadin.shared.annotations.Delayed;
import com.vaadin.shared.communication.ServerRpc;
/**
@@ -42,6 +43,27 @@ public interface AbstractDateFieldServerRpc extends ServerRpc {
void update(String newDateString, Map<String, Integer> resolutions);
/**
+ * Updates the typed data string and resolution names and values with
+ * delayed rpc. The rpc will be sent by triggering another non
+ * {@link Delayed} annotated rpc.
+ *
+ * @since
+ *
+ * @param newDateString
+ * the value of the text field part. It enables analyzing invalid
+ * input on the server. {@code null} if the date was chosen with
+ * popup calendar or contains user-typed string
+ * @param resolutions
+ * map of time unit (resolution) name and value, the key is the
+ * resolution name e.g. "HOUR", "MINUTE", the value can be
+ * {@code null}. If the map is empty, that means the
+ * {@code newDateString} is invalid
+ */
+ @Delayed(lastOnly = true)
+ void updateValueWithDelay(String newDateString,
+ Map<String, Integer> resolutions);
+
+ /**
* Indicates to the server that the client-side has lost focus.
*/
void blur();
diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateTimeFieldEventOrder.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateTimeFieldEventOrder.java
new file mode 100644
index 0000000000..420c83cca7
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateTimeFieldEventOrder.java
@@ -0,0 +1,54 @@
+package com.vaadin.tests.components.datefield;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.ValueChangeMode;
+import com.vaadin.shared.ui.datefield.DateTimeResolution;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.DateTimeField;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.TextField;
+import com.vaadin.v7.shared.ui.datefield.Resolution;
+import com.vaadin.v7.ui.DateField;
+
+@Widgetset(TestingWidgetSet.NAME)
+public class DateTimeFieldEventOrder extends AbstractTestUIWithLog {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+
+ HorizontalLayout horizontalLayout = new HorizontalLayout();
+
+ DateTimeField dateField = new DateTimeField();
+ dateField.setResolution(DateTimeResolution.SECOND);
+ dateField.setId("test-field");
+ dateField.addValueChangeListener(
+ event -> log("DateTimeField value change event"));
+
+ Button button = new Button("test");
+ button.setId("test-button");
+ button.addClickListener(ev -> {
+ log("Button Click Event");
+ });
+
+ TextField tf = new TextField("test");
+ tf.setValueChangeMode(ValueChangeMode.BLUR);
+ tf.addValueChangeListener(event -> log("TextField value change event"));
+
+ DateField df = new DateField();
+ df.setResolution(Resolution.SECOND);
+ df.addValueChangeListener(event -> {
+ log("DateTimeField V7 value change event");
+ });
+
+ horizontalLayout.addComponents(dateField, button, tf, df);
+ addComponent(horizontalLayout);
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 11316;
+ }
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/datefield/DateTimeFieldEventOrderTest.java b/uitest/src/test/java/com/vaadin/tests/components/datefield/DateTimeFieldEventOrderTest.java
new file mode 100644
index 0000000000..cead7d6f2b
--- /dev/null
+++ b/uitest/src/test/java/com/vaadin/tests/components/datefield/DateTimeFieldEventOrderTest.java
@@ -0,0 +1,39 @@
+package com.vaadin.tests.components.datefield;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.Select;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.DateTimeFieldElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class DateTimeFieldEventOrderTest extends SingleBrowserTest {
+
+ @Test
+ public void testEventOrderIsCorrect() {
+ openTestURL();
+
+ DateTimeFieldElement field = $(DateTimeFieldElement.class).first();
+
+ field.openPopup();
+
+ List<WebElement> timeSelects = findElement(
+ By.className("v-datefield-calendarpanel-time"))
+ .findElements(By.tagName("select"));
+
+ new Select(timeSelects.get(0)).selectByValue("09");
+
+ findElement(By.id("test-button")).click();
+
+ assertEquals("The button click event should come second.",
+ "2. Button Click Event", getLogRow(0));
+ assertEquals("The value change event of DTF should come firstly.",
+ "1. DateTimeField value change event", getLogRow(1));
+
+ }
+}