summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/src/main/java/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java26
-rw-r--r--server/src/main/java/com/vaadin/ui/NativeSelect.java56
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/combobox/ComboBoxDeclarativeTest.java7
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/nativeselect/NativeSelectDeclarativeTest.java21
-rw-r--r--shared/src/main/java/com/vaadin/shared/ui/nativeselect/NativeSelectState.java12
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/nativeselect/NativeSelectEmptySelection.java50
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/nativeselect/NativeSelects.java7
-rw-r--r--uitest/src/main/resources/com/vaadin/tests/components/nativeselect/TestComponent.html2
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/nativeselect/NativeSelectEmptySelectionTest.java71
9 files changed, 245 insertions, 7 deletions
diff --git a/client/src/main/java/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java b/client/src/main/java/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java
index 33c3170168..2426996ba4 100644
--- a/client/src/main/java/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java
+++ b/client/src/main/java/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java
@@ -17,6 +17,7 @@
package com.vaadin.client.ui.nativeselect;
import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.ui.ListBox;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.connectors.AbstractSingleSelectConnector;
import com.vaadin.client.data.DataSource;
@@ -91,6 +92,21 @@ public class NativeSelectConnector
getWidget().setTabIndex(getState().tabIndex);
}
+ @OnStateChange({ "emptySelectionCaption", "emptySelectionAllowed" })
+ private void onEmptySelectionCaptionChange() {
+ ListBox listBox = getWidget().getListBox();
+ boolean hasEmptyItem = listBox.getItemCount() > 0
+ && listBox.getValue(0).isEmpty();
+ if (hasEmptyItem && getState().emptySelectionAllowed) {
+ listBox.setItemText(0, getState().emptySelectionCaption);
+ } else if (hasEmptyItem && !getState().emptySelectionAllowed) {
+ listBox.removeItem(0);
+ } else if (!hasEmptyItem && getState().emptySelectionAllowed) {
+ listBox.insertItem(getState().emptySelectionCaption, 0);
+ listBox.setValue(0, "");
+ }
+ }
+
@Override
public NativeSelectState getState() {
return (NativeSelectState) super.getState();
@@ -112,9 +128,11 @@ public class NativeSelectConnector
final VNativeSelect select = getWidget();
final int itemCount = select.getListBox().getItemCount();
- for (int i = range.getStart(); i < range.getEnd(); i++) {
+ int increment = getState().emptySelectionAllowed ? 1 : 0;
+ for (int i = range.getStart() + increment; i < range.getEnd()
+ + increment; i++) {
- final JsonObject row = getDataSource().getRow(i);
+ final JsonObject row = getDataSource().getRow(i - increment);
if (i < itemCount) {
// Reuse and update an existing item
@@ -127,8 +145,8 @@ public class NativeSelectConnector
}
}
- for (int i = select.getListBox().getItemCount() - 1; i >= range
- .getEnd(); i--) {
+ for (int i = select.getListBox().getItemCount() - 1; i >= range.getEnd()
+ + increment; i--) {
// Remove extra items if the new dataset is smaller than the old
select.getListBox().removeItem(i);
}
diff --git a/server/src/main/java/com/vaadin/ui/NativeSelect.java b/server/src/main/java/com/vaadin/ui/NativeSelect.java
index 9ae3409b66..f7427568ff 100644
--- a/server/src/main/java/com/vaadin/ui/NativeSelect.java
+++ b/server/src/main/java/com/vaadin/ui/NativeSelect.java
@@ -17,6 +17,7 @@
package com.vaadin.ui;
import java.util.Collection;
+import java.util.Objects;
import com.vaadin.data.HasDataProvider;
import com.vaadin.data.provider.DataProvider;
@@ -139,4 +140,59 @@ public class NativeSelect<T> extends AbstractSingleSelect<T>
public ItemCaptionGenerator<T> getItemCaptionGenerator() {
return super.getItemCaptionGenerator();
}
+
+ /**
+ * Returns whether the user is allowed to select nothing in the combo box.
+ *
+ * @return true if empty selection is allowed, false otherwise
+ */
+ public boolean isEmptySelectionAllowed() {
+ return getState(false).emptySelectionAllowed;
+ }
+
+ /**
+ * Sets whether the user is allowed to select nothing in the combo box. When
+ * true, a special empty item is shown to the user.
+ *
+ * @param emptySelectionAllowed
+ * true to allow not selecting anything, false to require
+ * selection
+ */
+ public void setEmptySelectionAllowed(boolean emptySelectionAllowed) {
+ getState().emptySelectionAllowed = emptySelectionAllowed;
+ }
+
+ /**
+ * Returns the empty selection caption.
+ * <p>
+ * The empty string {@code ""} is the default empty selection caption.
+ *
+ * @see #setEmptySelectionAllowed(boolean)
+ * @see #isEmptySelectionAllowed()
+ * @see #setEmptySelectionCaption(String)
+ * @see #isSelected(Object)
+ *
+ * @return the empty selection caption, not {@code null}
+ */
+ public String getEmptySelectionCaption() {
+ return getState(false).emptySelectionCaption;
+ }
+
+ /**
+ * Sets the empty selection caption.
+ * <p>
+ * The empty string {@code ""} is the default empty selection caption.
+ * <p>
+ * If empty selection is allowed via the
+ * {@link #setEmptySelectionAllowed(boolean)} method (it is by default) then
+ * the empty item will be shown with the given caption.
+ *
+ * @param caption
+ * the caption to set, not {@code null}
+ * @see #isSelected(Object)
+ */
+ public void setEmptySelectionCaption(String caption) {
+ Objects.nonNull(caption);
+ getState().emptySelectionCaption = caption;
+ }
}
diff --git a/server/src/test/java/com/vaadin/tests/server/component/combobox/ComboBoxDeclarativeTest.java b/server/src/test/java/com/vaadin/tests/server/component/combobox/ComboBoxDeclarativeTest.java
index 1677f8699b..e2a0c67f2a 100644
--- a/server/src/test/java/com/vaadin/tests/server/component/combobox/ComboBoxDeclarativeTest.java
+++ b/server/src/test/java/com/vaadin/tests/server/component/combobox/ComboBoxDeclarativeTest.java
@@ -48,12 +48,14 @@ public class ComboBoxDeclarativeTest
int pageLength = 7;
String popupWidth = "11%";
boolean emptySelectionAllowed = false;
+ String emptySelectionCaption = "foo";
String design = String.format(
"<%s placeholder='%s' text-input-allowed='%s' page-length='%d' "
- + "popup-width='%s' empty-selection-allowed='%s' scroll-to-selected-item/>",
+ + "popup-width='%s' empty-selection-allowed='%s' "
+ + "scroll-to-selected-item empty-selection-caption='%s'/>",
getComponentTag(), placeholder, textInputAllowed, pageLength,
- popupWidth, emptySelectionAllowed);
+ popupWidth, emptySelectionAllowed, emptySelectionCaption);
ComboBox<String> comboBox = new ComboBox<>();
comboBox.setPlaceholder(placeholder);
@@ -62,6 +64,7 @@ public class ComboBoxDeclarativeTest
comboBox.setPopupWidth(popupWidth);
comboBox.setScrollToSelectedItem(true);
comboBox.setEmptySelectionAllowed(emptySelectionAllowed);
+ comboBox.setEmptySelectionCaption(emptySelectionCaption);
testRead(design, comboBox);
testWrite(design, comboBox);
diff --git a/server/src/test/java/com/vaadin/tests/server/component/nativeselect/NativeSelectDeclarativeTest.java b/server/src/test/java/com/vaadin/tests/server/component/nativeselect/NativeSelectDeclarativeTest.java
index 2b80546e80..fea6ac3b12 100644
--- a/server/src/test/java/com/vaadin/tests/server/component/nativeselect/NativeSelectDeclarativeTest.java
+++ b/server/src/test/java/com/vaadin/tests/server/component/nativeselect/NativeSelectDeclarativeTest.java
@@ -15,6 +15,8 @@
*/
package com.vaadin.tests.server.component.nativeselect;
+import org.junit.Test;
+
import com.vaadin.tests.server.component.abstractsingleselect.AbstractSingleSelectDeclarativeTest;
import com.vaadin.ui.NativeSelect;
@@ -29,6 +31,25 @@ import com.vaadin.ui.NativeSelect;
public class NativeSelectDeclarativeTest
extends AbstractSingleSelectDeclarativeTest<NativeSelect> {
+ @Test
+ public void nativeSelectSpecificPropertiesSerialize() {
+ boolean emptySelectionAllowed = false;
+ String emptySelectionCaption = "foo";
+
+ String design = String.format(
+ "<%s empty-selection-allowed='%s' "
+ + "empty-selection-caption='%s'/>",
+ getComponentTag(), emptySelectionAllowed,
+ emptySelectionCaption);
+
+ NativeSelect<String> select = new NativeSelect<>();
+ select.setEmptySelectionAllowed(emptySelectionAllowed);
+ select.setEmptySelectionCaption(emptySelectionCaption);
+
+ testRead(design, select);
+ testWrite(design, select);
+ }
+
@Override
protected String getComponentTag() {
return "vaadin-native-select";
diff --git a/shared/src/main/java/com/vaadin/shared/ui/nativeselect/NativeSelectState.java b/shared/src/main/java/com/vaadin/shared/ui/nativeselect/NativeSelectState.java
index e4ff336e4d..c33cc66f82 100644
--- a/shared/src/main/java/com/vaadin/shared/ui/nativeselect/NativeSelectState.java
+++ b/shared/src/main/java/com/vaadin/shared/ui/nativeselect/NativeSelectState.java
@@ -31,6 +31,18 @@ public class NativeSelectState extends AbstractSingleSelectState {
*/
public static final String STYLE_NAME = "v-select";
+ /**
+ * True to allow selecting nothing (a special empty selection item is shown
+ * at the beginning of the list), false not to allow empty selection by the
+ * user.
+ */
+ public boolean emptySelectionAllowed = true;
+
+ /**
+ * Caption for item which represents empty selection.
+ */
+ public String emptySelectionCaption = "";
+
{
primaryStyleName = STYLE_NAME;
}
diff --git a/uitest/src/main/java/com/vaadin/tests/components/nativeselect/NativeSelectEmptySelection.java b/uitest/src/main/java/com/vaadin/tests/components/nativeselect/NativeSelectEmptySelection.java
new file mode 100644
index 0000000000..2d222490f6
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/tests/components/nativeselect/NativeSelectEmptySelection.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.nativeselect;
+
+import java.util.stream.IntStream;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.NativeSelect;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class NativeSelectEmptySelection extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ NativeSelect<String> select = new NativeSelect<>();
+ select.setItems(IntStream.range(1, 50)
+ .mapToObj(index -> String.valueOf(index)));
+ select.setEmptySelectionCaption("empty");
+ addComponent(select);
+
+ Button update = new Button("Update Empty Caption to 'updated'",
+ event -> select.setEmptySelectionCaption("updated"));
+
+ Button disallow = new Button("Disallow empty selection item",
+ event -> select.setEmptySelectionAllowed(false));
+
+ Button enable = new Button("Allow empty selection item",
+ event -> select.setEmptySelectionAllowed(true));
+ addComponents(update, disallow, enable);
+ }
+
+}
diff --git a/uitest/src/main/java/com/vaadin/tests/components/nativeselect/NativeSelects.java b/uitest/src/main/java/com/vaadin/tests/components/nativeselect/NativeSelects.java
index 1a28fd41fb..34b78089bb 100644
--- a/uitest/src/main/java/com/vaadin/tests/components/nativeselect/NativeSelects.java
+++ b/uitest/src/main/java/com/vaadin/tests/components/nativeselect/NativeSelects.java
@@ -11,4 +11,11 @@ public class NativeSelects
protected Class<NativeSelect<Object>> getTestClass() {
return (Class) NativeSelect.class;
}
+
+ @Override
+ protected NativeSelect<Object> constructComponent() {
+ NativeSelect<Object> component = super.constructComponent();
+ component.setEmptySelectionAllowed(false);
+ return component;
+ }
}
diff --git a/uitest/src/main/resources/com/vaadin/tests/components/nativeselect/TestComponent.html b/uitest/src/main/resources/com/vaadin/tests/components/nativeselect/TestComponent.html
index f4228bf60f..17adb460e4 100644
--- a/uitest/src/main/resources/com/vaadin/tests/components/nativeselect/TestComponent.html
+++ b/uitest/src/main/resources/com/vaadin/tests/components/nativeselect/TestComponent.html
@@ -7,7 +7,7 @@
<body>
<vaadin-vertical-layout>
<vaadin-horizontal-layout _id="buttons" width-full></vaadin-horizontal-layout>
- <vaadin-native-select _id="nativeSelect">
+ <vaadin-native-select _id="nativeSelect" empty-selection-allowed="false">
<option item="Option 1">Foo</option>
<option item="Option 2">Bar</option>
<option item="Option 3">Baz</option>
diff --git a/uitest/src/test/java/com/vaadin/tests/components/nativeselect/NativeSelectEmptySelectionTest.java b/uitest/src/test/java/com/vaadin/tests/components/nativeselect/NativeSelectEmptySelectionTest.java
new file mode 100644
index 0000000000..102b504605
--- /dev/null
+++ b/uitest/src/test/java/com/vaadin/tests/components/nativeselect/NativeSelectEmptySelectionTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.nativeselect;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.NativeSelectElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class NativeSelectEmptySelectionTest extends MultiBrowserTest {
+
+ @Test
+ public void checkEmptySelection() {
+ openTestURL();
+
+ checkOptions("empty");
+
+ // change the caption
+ $(ButtonElement.class).first().click();
+ checkOptions("updated");
+
+ // disable empty caption
+ $(ButtonElement.class).get(1).click();
+ checkOptions(null);
+
+ // enable back
+ $(ButtonElement.class).get(2).click();
+ checkOptions("updated");
+ }
+
+ private void checkOptions(String emptyCaption) {
+ NativeSelectElement select = $(NativeSelectElement.class).first();
+ Set<String> originalOptions = IntStream.range(1, 50)
+ .mapToObj(index -> String.valueOf(index))
+ .collect(Collectors.toSet());
+ Set<String> options = select.getOptions().stream()
+ .map(TestBenchElement::getText).collect(Collectors.toSet());
+ if (emptyCaption == null) {
+ Assert.assertEquals(49, options.size());
+ Assert.assertTrue(options.containsAll(originalOptions));
+ } else {
+ options.contains(emptyCaption);
+ Assert.assertEquals(50, options.size());
+ Assert.assertTrue(options.containsAll(originalOptions));
+ }
+ }
+}