summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--all/src/main/templates/release-notes.html2
-rw-r--r--client/src/main/java/com/vaadin/client/connectors/grid/EditorConnector.java27
-rw-r--r--server/src/main/java/com/vaadin/data/provider/DataCommunicator.java2
-rw-r--r--server/src/main/java/com/vaadin/data/provider/HierarchicalDataCommunicator.java2
-rw-r--r--server/src/main/java/com/vaadin/ui/components/grid/Editor.java10
-rw-r--r--server/src/main/java/com/vaadin/ui/components/grid/EditorImpl.java37
-rw-r--r--shared/src/main/java/com/vaadin/shared/ui/grid/editor/EditorClientRpc.java9
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java5
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridEditorTest.java29
9 files changed, 118 insertions, 5 deletions
diff --git a/all/src/main/templates/release-notes.html b/all/src/main/templates/release-notes.html
index fda12e0a2d..20a7346182 100644
--- a/all/src/main/templates/release-notes.html
+++ b/all/src/main/templates/release-notes.html
@@ -113,7 +113,7 @@
<li>Row height in <tt>Grid</tt> is replaced with separate header, body and footer row heights</li>
<li><tt>GridState</tt> variable <tt>rowHeight</tt> has been replaced by three variables.</li>
<li><tt>Button</tt> has a new constructor that may cause constructor calls with null as first parameter to be ambiguous.</li>
- <li><tt>DataCommunicator</tt> method <tt>getDataProviderSize</tt> is now <tt>public</tt>, not <tt>protected</tt>.</li>
+ <li><tt>DataCommunicator</tt> methods <tt>getDataProviderSize</tt> and <tt>fetchItemsWithRange</tt> are now <tt>public</tt>, not <tt>protected</tt>.</li>
<li><tt>Binder</tt> method <tt>getBindings</tt> now returns a Collection, not a Set.</li>
<li><tt>BindingBuilder</tt> now works like a proper builder. Adding a converter will not mark Binding as <tt>bound</tt> allowing chaining to the same object.</li>
<li><tt>ErrorLevel</tt> is removed from <tt>ErrorMessage</tt> and now <tt>com.vaadin.shared.ui.ErrorLevel</tt> should be used.</li>
diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/EditorConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/EditorConnector.java
index 50704c4262..c8c60c9620 100644
--- a/client/src/main/java/com/vaadin/client/connectors/grid/EditorConnector.java
+++ b/client/src/main/java/com/vaadin/client/connectors/grid/EditorConnector.java
@@ -19,6 +19,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import com.google.gwt.core.client.Scheduler;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorMap;
@@ -28,6 +29,7 @@ import com.vaadin.client.extensions.AbstractExtensionConnector;
import com.vaadin.client.widget.grid.EditorHandler;
import com.vaadin.client.widgets.Grid;
import com.vaadin.client.widgets.Grid.Column;
+import com.vaadin.shared.Range;
import com.vaadin.shared.data.DataCommunicatorConstants;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.grid.editor.EditorClientRpc;
@@ -46,6 +48,9 @@ import elemental.json.JsonObject;
@Connect(EditorImpl.class)
public class EditorConnector extends AbstractExtensionConnector {
+ private Integer currentEditedRow = null;
+ private boolean waitingForAvailableData = false;
+
/**
* EditorHandler for communicating with the server-side implementation.
*/
@@ -56,6 +61,20 @@ public class EditorConnector extends AbstractExtensionConnector {
public CustomEditorHandler() {
registerRpc(EditorClientRpc.class, new EditorClientRpc() {
+
+ @Override
+ public void bind(final int rowIndex) {
+ // call this deferred to avoid issues with editing on init
+ Scheduler.get().scheduleDeferred(() -> {
+ currentEditedRow = rowIndex;
+ // might need to wait for available data,
+ // if data is available, ensureAvailability will immediately trigger the handler anyway,
+ // so no need for alternative "immediately available" logic
+ waitingForAvailableData = true;
+ getParent().getDataSource().ensureAvailability(rowIndex, 1);
+ });
+ }
+
@Override
public void cancel() {
serverInitiated = true;
@@ -110,6 +129,7 @@ public class EditorConnector extends AbstractExtensionConnector {
// a confirmation from the server
rpc.cancel(afterBeingSaved);
}
+ currentEditedRow = null;
}
@Override
@@ -198,6 +218,13 @@ public class EditorConnector extends AbstractExtensionConnector {
protected void extend(ServerConnector target) {
Grid<JsonObject> grid = getParent().getWidget();
grid.getEditor().setHandler(new CustomEditorHandler());
+ grid.addDataAvailableHandler((event) -> {
+ Range range = event.getAvailableRows();
+ if (waitingForAvailableData && currentEditedRow != null && range.contains(currentEditedRow)) {
+ getParent().getWidget().editRow(currentEditedRow);
+ waitingForAvailableData = false;
+ }
+ });
}
@Override
diff --git a/server/src/main/java/com/vaadin/data/provider/DataCommunicator.java b/server/src/main/java/com/vaadin/data/provider/DataCommunicator.java
index 9996d8d1aa..66bf758efe 100644
--- a/server/src/main/java/com/vaadin/data/provider/DataCommunicator.java
+++ b/server/src/main/java/com/vaadin/data/provider/DataCommunicator.java
@@ -370,7 +370,7 @@ public class DataCommunicator<T> extends AbstractExtension {
* @since 8.1
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
- protected List<T> fetchItemsWithRange(int offset, int limit) {
+ public List<T> fetchItemsWithRange(int offset, int limit) {
return (List<T>) getDataProvider().fetch(new Query(offset, limit,
backEndSorting, inMemorySorting, filter))
.collect(Collectors.toList());
diff --git a/server/src/main/java/com/vaadin/data/provider/HierarchicalDataCommunicator.java b/server/src/main/java/com/vaadin/data/provider/HierarchicalDataCommunicator.java
index 627cc28651..b0397ffcc7 100644
--- a/server/src/main/java/com/vaadin/data/provider/HierarchicalDataCommunicator.java
+++ b/server/src/main/java/com/vaadin/data/provider/HierarchicalDataCommunicator.java
@@ -66,7 +66,7 @@ public class HierarchicalDataCommunicator<T> extends DataCommunicator<T> {
}
@Override
- protected List<T> fetchItemsWithRange(int offset, int limit) {
+ public List<T> fetchItemsWithRange(int offset, int limit) {
// Instead of adding logic to this class, delegate request to the
// separate object handling hierarchies.
return mapper.fetchItems(Range.withLength(offset, limit))
diff --git a/server/src/main/java/com/vaadin/ui/components/grid/Editor.java b/server/src/main/java/com/vaadin/ui/components/grid/Editor.java
index 26ef8101ab..8c34fbdf64 100644
--- a/server/src/main/java/com/vaadin/ui/components/grid/Editor.java
+++ b/server/src/main/java/com/vaadin/ui/components/grid/Editor.java
@@ -104,6 +104,16 @@ public interface Editor<T> extends Serializable {
public void cancel();
/**
+ * Edits the selected row
+ *
+ * @param rowNumber
+ * the row to edit
+ *
+ * @since 8.2
+ */
+ public void editRow(int rowNumber);
+
+ /**
* Sets the caption of the save button in buffered mode.
*
* @param saveCaption
diff --git a/server/src/main/java/com/vaadin/ui/components/grid/EditorImpl.java b/server/src/main/java/com/vaadin/ui/components/grid/EditorImpl.java
index 4d5e91b671..7329677ca3 100644
--- a/server/src/main/java/com/vaadin/ui/components/grid/EditorImpl.java
+++ b/server/src/main/java/com/vaadin/ui/components/grid/EditorImpl.java
@@ -267,6 +267,43 @@ public class EditorImpl<T> extends AbstractGridExtension<T>
rpc.cancel();
}
+ /**
+ * Opens the editor interface for the provided row. Scrolls the Grid to
+ * bring the row to view if it is not already visible.
+ *
+ * Note that any cell content rendered by a WidgetRenderer will not be
+ * visible in the editor row.
+ *
+ * @param rowNumber
+ * the row number of the edited item
+ * @throws IllegalStateException
+ * if the editor is not enabled or already editing a different item
+ * in buffered mode
+ * @throws IllegalArgumentException
+ * if the {@code rowNumber} is not in the backing data provider
+ * @see #setEnabled(boolean)
+ */
+ public void editRow(int rowNumber)
+ throws IllegalStateException, IllegalArgumentException {
+ if (!isEnabled()) {
+ throw new IllegalStateException("Item editor is not enabled");
+ }
+ T beanToEdit = getParent().getDataCommunicator().
+ fetchItemsWithRange(rowNumber, 1).
+ stream().findFirst().orElseThrow(() -> new IllegalArgumentException(
+ "Row number " + rowNumber+ "did not yield any item from data provider"));
+ if (!beanToEdit.equals(edited)) {
+ if (isBuffered() && edited != null) {
+ throw new IllegalStateException("Editing item " + beanToEdit
+ + " failed. Item editor is already editing item "
+ + edited);
+ } else {
+ rpc.bind(rowNumber);
+ }
+ }
+
+ }
+
private void doCancel(boolean afterBeingSaved) {
T editedBean = edited;
doClose();
diff --git a/shared/src/main/java/com/vaadin/shared/ui/grid/editor/EditorClientRpc.java b/shared/src/main/java/com/vaadin/shared/ui/grid/editor/EditorClientRpc.java
index ff4ca4c614..e278e7716b 100644
--- a/shared/src/main/java/com/vaadin/shared/ui/grid/editor/EditorClientRpc.java
+++ b/shared/src/main/java/com/vaadin/shared/ui/grid/editor/EditorClientRpc.java
@@ -28,6 +28,15 @@ import com.vaadin.shared.communication.ClientRpc;
public interface EditorClientRpc extends ClientRpc {
/**
+ * Tells the client to open the editor and bind data to it.
+ *
+ * @param rowIndex
+ * the index of the edited row
+ *
+ */
+ void bind(int rowIndex);
+
+ /**
* Tells the client to cancel editing and hide the editor.
*/
void cancel();
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java b/uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java
index 56d970308d..c9144e52f0 100644
--- a/uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java
+++ b/uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java
@@ -763,6 +763,11 @@ public class GridBasics extends AbstractTestUIWithLog {
editorMenu.addItem("Save", i -> grid.getEditor().save());
editorMenu.addItem("Cancel edit", i -> grid.getEditor().cancel());
+ Stream.of(0, 5, 100).forEach(i -> editorMenu.addItem("Edit row " + i,
+ menuItem -> grid.getEditor().editRow(i)));
+ editorMenu.addItem("Edit last row", menuItem -> grid.getEditor()
+ .editRow(grid.getDataCommunicator().getDataProviderSize() - 1));
+
editorMenu.addItem("Change save caption",
e -> grid.getEditor().setSaveCaption("ǝʌɐS"));
editorMenu.addItem("Change cancel caption",
diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridEditorTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridEditorTest.java
index d8a49a5938..832e5e6651 100644
--- a/uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridEditorTest.java
+++ b/uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridEditorTest.java
@@ -19,6 +19,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@@ -37,8 +38,8 @@ public abstract class GridEditorTest extends GridBasicsTest {
.className("v-grid-editor-cancel");
protected static final org.openqa.selenium.By BY_EDITOR_SAVE = By
.className("v-grid-editor-save");
- protected static final String[] TOGGLE_EDIT_ENABLED = {
- "Component", "Editor", "Enabled" };
+ protected static final String[] TOGGLE_EDIT_ENABLED = { "Component",
+ "Editor", "Enabled" };
@Override
@Before
@@ -216,6 +217,30 @@ public abstract class GridEditorTest extends GridBasicsTest {
assertEditorClosed();
}
+ @Test
+ public void testEditorOpeningFromServer() {
+ selectMenuPath("Component", "Editor", "Edit row 5");
+ assertEditorOpen();
+
+ Assert.assertEquals("Unexpected editor field content", "5",
+ getEditor().getField(3).getAttribute("value"));
+ Assert.assertEquals("Unexpected not-editable column content", "(5, 1)",
+ getEditor().findElement(By.className("not-editable"))
+ .getText());
+ }
+
+ @Test
+ public void testEditorOpenWithScrollFromServer() {
+ selectMenuPath("Component", "Editor", "Edit last row");
+ assertEditorOpen();
+
+ Assert.assertEquals("Unexpected editor field content", "999",
+ getEditor().getField(3).getAttribute("value"));
+ Assert.assertEquals("Unexpected not-editable column content",
+ "(999, 1)", getEditor()
+ .findElement(By.className("not-editable")).getText());
+ }
+
protected WebElement getSaveButton() {
return getDriver().findElement(BY_EDITOR_SAVE);
}