diff options
author | patrik <patrik@vaadin.com> | 2015-08-26 14:48:45 +0300 |
---|---|---|
committer | Johannes Dahlström <johannesd@vaadin.com> | 2015-09-01 13:36:58 +0300 |
commit | 9899aa2009d32e375ccd21e2edf50cb6d2d557bb (patch) | |
tree | 6494a0dec0c85ffcb0a122c252eff4b210a4a378 | |
parent | 86a22c9a733e63cb6fc60e87bc6789b70c67b9d4 (diff) | |
download | vaadin-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.java | 100 | ||||
-rw-r--r-- | client/src/com/vaadin/client/ui/AbstractConnector.java | 2 | ||||
-rw-r--r-- | client/src/com/vaadin/client/widgets/Grid.java | 34 |
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) { |