Просмотр исходного кода

Introduce empty selection functionality for NativeSelect. (#8336)

* Introduce empty selection functionality for NativeSelect.

Fixes vaadin/framework8-issues#545
tags/8.0.0.beta2
Denis 7 лет назад
Родитель
Сommit
9ef479303b

+ 22
- 4
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);
}

+ 56
- 0
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;
}
}

+ 5
- 2
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);

+ 21
- 0
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";

+ 12
- 0
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;
}

+ 50
- 0
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);
}

}

+ 7
- 0
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;
}
}

+ 1
- 1
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>

+ 71
- 0
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));
}
}
}

Загрузка…
Отмена
Сохранить