summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpatrik <patrik@vaadin.com>2015-08-26 14:48:45 +0300
committerJohannes Dahlström <johannesd@vaadin.com>2015-09-01 13:36:58 +0300
commit9899aa2009d32e375ccd21e2edf50cb6d2d557bb (patch)
tree6494a0dec0c85ffcb0a122c252eff4b210a4a378
parent86a22c9a733e63cb6fc60e87bc6789b70c67b9d4 (diff)
downloadvaadin-framework-9899aa2009d32e375ccd21e2edf50cb6d2d557bb.tar.gz
vaadin-framework-9899aa2009d32e375ccd21e2edf50cb6d2d557bb.zip
Make Grid Editor eagerly report validation errors (#16725)
Change-Id: I56b60d5bf30dde7cc73bc6b339150b9114e95d72
-rw-r--r--client/src/com/vaadin/client/connectors/GridConnector.java100
-rw-r--r--client/src/com/vaadin/client/ui/AbstractConnector.java2
-rw-r--r--client/src/com/vaadin/client/widgets/Grid.java34
3 files changed, 123 insertions, 13 deletions
diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java
index 74f8a96bc0..5f9341c068 100644
--- a/client/src/com/vaadin/client/connectors/GridConnector.java
+++ b/client/src/com/vaadin/client/connectors/GridConnector.java
@@ -33,6 +33,8 @@ import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Widget;
@@ -40,9 +42,10 @@ import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
import com.vaadin.client.DeferredWorker;
import com.vaadin.client.MouseEventDetailsBuilder;
-import com.vaadin.client.TooltipInfo;
import com.vaadin.client.ServerConnector;
+import com.vaadin.client.TooltipInfo;
import com.vaadin.client.communication.StateChangeEvent;
+import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler;
import com.vaadin.client.connectors.RpcDataSourceConnector.DetailsListener;
import com.vaadin.client.connectors.RpcDataSourceConnector.RpcDataSource;
import com.vaadin.client.data.DataSource.RowHandle;
@@ -170,6 +173,8 @@ public class GridConnector extends AbstractHasComponentsConnector implements
private AbstractFieldConnector editorConnector;
+ private HandlerRegistration errorStateHandler;
+
public CustomGridColumn(String id,
AbstractRendererConnector<Object> rendererConnector) {
super(rendererConnector.getRenderer());
@@ -206,8 +211,54 @@ public class GridConnector extends AbstractHasComponentsConnector implements
return editorConnector;
}
- private void setEditorConnector(AbstractFieldConnector editorConnector) {
+ private void setEditorConnector(
+ final AbstractFieldConnector editorConnector) {
this.editorConnector = editorConnector;
+
+ if (errorStateHandler != null) {
+ errorStateHandler.removeHandler();
+ errorStateHandler = null;
+ }
+
+ // Avoid nesting too deep
+ if (editorConnector == null) {
+ return;
+ }
+
+ errorStateHandler = editorConnector.addStateChangeHandler(
+ "errorMessage", new StateChangeHandler() {
+
+ @Override
+ public void onStateChanged(
+ StateChangeEvent stateChangeEvent) {
+
+ String error = editorConnector.getState().errorMessage;
+
+ if (error == null) {
+ columnToErrorMessage
+ .remove(CustomGridColumn.this);
+ } else {
+ // The error message is formatted as HTML;
+ // therefore, we use this hack to make the
+ // string human-readable.
+ Element e = DOM.createElement("div");
+ e.setInnerHTML(editorConnector.getState().errorMessage);
+ error = getHeaderCaption() + ": "
+ + e.getInnerText();
+
+ columnToErrorMessage.put(CustomGridColumn.this,
+ error);
+ }
+
+ // Editor should not be touched while there's a
+ // request pending.
+ if (editorHandler.currentRequest == null) {
+ getWidget().getEditor().setEditorError(
+ getColumnErrors(),
+ columnToErrorMessage.keySet());
+ }
+ }
+ });
}
}
@@ -282,7 +333,12 @@ public class GridConnector extends AbstractHasComponentsConnector implements
if (column instanceof CustomGridColumn) {
AbstractFieldConnector c = ((CustomGridColumn) column)
.getEditorConnector();
- return c != null ? c.getWidget() : null;
+
+ if (c == null) {
+ return null;
+ }
+
+ return c.getWidget();
} else {
throw new IllegalStateException("Unexpected column type: "
+ column.getClass().getName());
@@ -575,6 +631,9 @@ public class GridConnector extends AbstractHasComponentsConnector implements
}
};
+ /* Used to track Grid editor columns with validation errors */
+ private final Map<Column<?, JsonObject>, String> columnToErrorMessage = new HashMap<Column<?, JsonObject>, String>();
+
private ItemClickHandler itemClickHandler = new ItemClickHandler();
private String lastKnownTheme = null;
@@ -616,6 +675,7 @@ public class GridConnector extends AbstractHasComponentsConnector implements
};
private final LazyDetailsScroller lazyDetailsScroller = new LazyDetailsScroller();
+ private final CustomEditorHandler editorHandler = new CustomEditorHandler();
/*
* Initially details need to behave a bit differently to allow some
@@ -749,7 +809,7 @@ public class GridConnector extends AbstractHasComponentsConnector implements
});
- getWidget().setEditorHandler(new CustomEditorHandler());
+ getWidget().setEditorHandler(editorHandler);
getWidget().addColumnReorderHandler(columnReorderHandler);
getWidget().addColumnVisibilityChangeHandler(
columnVisibilityChangeHandler);
@@ -1326,4 +1386,36 @@ public class GridConnector extends AbstractHasComponentsConnector implements
return super.getTooltipInfo(element);
}
+
+ /**
+ * Creates a concatenation of all columns errors for Editor.
+ *
+ * @since
+ * @return displayed error string
+ */
+ private String getColumnErrors() {
+ List<String> errors = new ArrayList<String>();
+
+ for (Grid.Column<?, JsonObject> c : getWidget().getColumns()) {
+ if (!(c instanceof CustomGridColumn)) {
+ continue;
+ }
+
+ String error = columnToErrorMessage.get(c);
+ if (error != null) {
+ errors.add(error);
+ }
+ }
+
+ String result = "";
+ Iterator<String> i = errors.iterator();
+ while (i.hasNext()) {
+ result += i.next();
+ if (i.hasNext()) {
+ result += ", ";
+ }
+ }
+ return result.isEmpty() ? null : result;
+ }
+
}
diff --git a/client/src/com/vaadin/client/ui/AbstractConnector.java b/client/src/com/vaadin/client/ui/AbstractConnector.java
index a20c3463c2..7f8d6c2b14 100644
--- a/client/src/com/vaadin/client/ui/AbstractConnector.java
+++ b/client/src/com/vaadin/client/ui/AbstractConnector.java
@@ -25,7 +25,7 @@ import java.util.Set;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerManager;
-import com.google.web.bindery.event.shared.HandlerRegistration;
+import com.google.gwt.event.shared.HandlerRegistration;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.FastStringMap;
import com.vaadin.client.FastStringSet;
diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java
index 7250ed76be..a2eedf4203 100644
--- a/client/src/com/vaadin/client/widgets/Grid.java
+++ b/client/src/com/vaadin/client/widgets/Grid.java
@@ -1091,14 +1091,10 @@ public class Grid<T> extends ResizeComposite implements
}
completed = true;
- grid.getEditor().setErrorMessage(errorMessage);
-
- grid.getEditor().clearEditorColumnErrors();
- if (errorColumns != null) {
- for (Column<?, T> column : errorColumns) {
- grid.getEditor().setEditorColumnError(column, true);
- }
+ if (errorColumns == null) {
+ errorColumns = Collections.emptySet();
}
+ grid.getEditor().setEditorError(errorMessage, errorColumns);
}
@Override
@@ -1224,6 +1220,9 @@ public class Grid<T> extends ResizeComposite implements
*/
public static class Editor<T> {
+ public static final int KEYCODE_SHOW = KeyCodes.KEY_ENTER;
+ public static final int KEYCODE_HIDE = KeyCodes.KEY_ESCAPE;
+
private static final String ERROR_CLASS_NAME = "error";
private static final String NOT_EDITABLE_CLASS_NAME = "not-editable";
@@ -1407,7 +1406,9 @@ public class Grid<T> extends ResizeComposite implements
});
}
- public void setErrorMessage(String errorMessage) {
+ public void setEditorError(String errorMessage,
+ Collection<Column<?, T>> errorColumns) {
+
if (errorMessage == null) {
message.removeFromParent();
} else {
@@ -1420,6 +1421,13 @@ public class Grid<T> extends ResizeComposite implements
if (!isBuffered()) {
setMessageAndButtonsWrapperVisible(errorMessage != null);
}
+
+ if (state == State.ACTIVE || state == State.SAVING) {
+ for (Column<?, T> c : grid.getColumns()) {
+ grid.getEditor().setEditorColumnError(c,
+ errorColumns.contains(c));
+ }
+ }
}
public int getRow() {
@@ -4568,6 +4576,16 @@ public class Grid<T> extends ResizeComposite implements
return this;
}
+ /**
+ * Returns the current header caption for this column
+ *
+ * @since
+ * @return the header caption string
+ */
+ public String getHeaderCaption() {
+ return headerCaption;
+ }
+
private void updateHeader() {
HeaderRow row = grid.getHeader().getDefaultRow();
if (row != null) {