diff --git a/pom.xml b/pom.xml index 6758801..51abc71 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.flowingcode.vaadin.addons twincolgrid - 3.0.1-SNAPSHOT + 3.1.0-SNAPSHOT TwinColGrid add-on Dual list component based on Vaadin Grids https://www.flowingcode.com/en/open-source/ diff --git a/src/main/java/com/flowingcode/vaadin/addons/twincolgrid/TwinColGrid.java b/src/main/java/com/flowingcode/vaadin/addons/twincolgrid/TwinColGrid.java index abc1f87..c548c20 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/twincolgrid/TwinColGrid.java +++ b/src/main/java/com/flowingcode/vaadin/addons/twincolgrid/TwinColGrid.java @@ -2,7 +2,7 @@ * #%L * TwinColGrid add-on * %% - * Copyright (C) 2017 - 2022 Flowing Code + * Copyright (C) 2017 - 2025 Flowing Code * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import com.vaadin.flow.component.ComponentUtil; import com.vaadin.flow.component.HasComponents; import com.vaadin.flow.component.HasSize; +import com.vaadin.flow.component.HasValidation; import com.vaadin.flow.component.HasValue; import com.vaadin.flow.component.HasValue.ValueChangeEvent; import com.vaadin.flow.component.HasValueAndElement; @@ -79,7 +80,7 @@ @CssImport(value = "./styles/twin-col-grid-button.css") @CssImport(value = "./styles/twincol-grid.css") public class TwinColGrid extends VerticalLayout - implements HasValueAndElement>, Set>, HasComponents, HasSize { + implements HasValueAndElement>, Set>, HasComponents, HasSize, HasValidation { private static final class TwinColModel implements Serializable { final Grid grid; @@ -142,6 +143,8 @@ public enum Orientation { private Span fakeButtonContainerLabel = new Span(); + private Span errorMessageSpan = new Span(); + private Orientation orientation = Orientation.HORIZONTAL; private boolean autoResize = false; @@ -184,7 +187,10 @@ public TwinColGrid(@NonNull Grid availableGrid, @NonNull Grid selectionGri available = new TwinColModel<>(availableGrid, "twincol-grid-available"); selection = new TwinColModel<>(selectionGrid, "twincol-grid-selection"); - + + errorMessageSpan.setClassName("twincol-grid-error-message"); + selection.layout.addComponentAtIndex(1, errorMessageSpan); + setClassName("twincol-grid"); setMargin(false); @@ -677,6 +683,26 @@ public boolean isRequiredIndicatorVisible() { return getElement().getAttribute("required") != null; } + @Override + public void setErrorMessage(String errorMessage) { + errorMessageSpan.setText(errorMessage); + } + + @Override + public String getErrorMessage() { + return errorMessageSpan.getText(); + } + + @Override + public void setInvalid(boolean invalid) { + getElement().setAttribute("invalid", invalid); + } + + @Override + public boolean isInvalid() { + return getElement().getAttribute("invalid") != null; + } + @Override public void setReadOnly(final boolean readOnly) { getAvailableGrid().setSelectionMode(readOnly ? SelectionMode.NONE : SelectionMode.MULTI); @@ -956,4 +982,5 @@ private void updateOrientationOnResize(int width, int height) { this.withOrientation(Orientation.HORIZONTAL); } } + } diff --git a/src/main/java/com/flowingcode/vaadin/addons/twincolgrid/TwinColGridListAdapter.java b/src/main/java/com/flowingcode/vaadin/addons/twincolgrid/TwinColGridListAdapter.java index bf06719..753ca3b 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/twincolgrid/TwinColGridListAdapter.java +++ b/src/main/java/com/flowingcode/vaadin/addons/twincolgrid/TwinColGridListAdapter.java @@ -2,7 +2,7 @@ * #%L * TwinColGrid add-on * %% - * Copyright (C) 2017 - 2022 Flowing Code + * Copyright (C) 2017 - 2025 Flowing Code * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ */ package com.flowingcode.vaadin.addons.twincolgrid; +import com.vaadin.flow.component.HasValidation; import com.vaadin.flow.component.HasValue; import com.vaadin.flow.component.HasValue.ValueChangeEvent; import com.vaadin.flow.shared.Registration; @@ -40,9 +41,9 @@ */ @SuppressWarnings("serial") @RequiredArgsConstructor -class TwinColGridListAdapter implements HasValue>, List> { +class TwinColGridListAdapter implements HasValue>, List>, HasValidation { - private interface IDelegate { + private interface IDelegate extends HasValidation { boolean isEmpty(); void clear(); diff --git a/src/main/resources/META-INF/resources/frontend/styles/twincol-grid.css b/src/main/resources/META-INF/resources/frontend/styles/twincol-grid.css index f21c973..759babd 100644 --- a/src/main/resources/META-INF/resources/frontend/styles/twincol-grid.css +++ b/src/main/resources/META-INF/resources/frontend/styles/twincol-grid.css @@ -2,7 +2,7 @@ * #%L * TwinColGrid add-on * %% - * Copyright (C) 2017 - 2022 Flowing Code + * Copyright (C) 2017 - 2025 Flowing Code * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,6 +44,19 @@ color: var(--lumo-error-text-color); } +.twincol-grid .twincol-grid-selection .twincol-grid-error-message { + display: none; +} + +.twincol-grid[invalid] .twincol-grid-selection .twincol-grid-error-message { + font-size: var(--vaadin-input-field-error-font-size, var(--lumo-font-size-xs)); + line-height: var(--lumo-line-height-xs); + font-weight: var(--vaadin-input-field-error-font-weight, 400); + color: var(--vaadin-input-field-error-color, var(--lumo-error-text-color)); + display: block; + padding-bottom: 4px; +} + .twincol-grid .fake-button-container-label { font-size: var(--lumo-font-size-s); margin-bottom: calc(var(--vaadin-button-margin, var(--lumo-space-xs))* -1); diff --git a/src/test/java/com/flowingcode/vaadin/addons/twincolgrid/BoundDemo.java b/src/test/java/com/flowingcode/vaadin/addons/twincolgrid/BoundDemo.java index 56c99d1..113e41c 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/twincolgrid/BoundDemo.java +++ b/src/test/java/com/flowingcode/vaadin/addons/twincolgrid/BoundDemo.java @@ -2,7 +2,7 @@ * #%L * TwinColGrid add-on * %% - * Copyright (C) 2017 - 2022 Flowing Code + * Copyright (C) 2017 - 2025 Flowing Code * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,7 +58,9 @@ public BoundDemo() { twinColGrid.setCaption("TwinColGrid demo with Binder and row select without checkbox"); final Binder binder = new Binder<>(); - binder.forField(twinColGrid.asList()).asRequired().bind(Library::getBooks, Library::setBooks); + binder.forField(twinColGrid.asList()) + .asRequired("You must add at least one book.") + .bind(Library::getBooks, Library::setBooks); binder.setBean(library); add(twinColGrid);