aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/main')
-rw-r--r--server/src/main/java/com/vaadin/data/BeanBinder.java19
-rw-r--r--server/src/main/java/com/vaadin/data/Binder.java121
-rw-r--r--server/src/main/java/com/vaadin/ui/AbstractSingleSelect.java11
3 files changed, 130 insertions, 21 deletions
diff --git a/server/src/main/java/com/vaadin/data/BeanBinder.java b/server/src/main/java/com/vaadin/data/BeanBinder.java
index dd5790b8b6..64436c26a8 100644
--- a/server/src/main/java/com/vaadin/data/BeanBinder.java
+++ b/server/src/main/java/com/vaadin/data/BeanBinder.java
@@ -20,7 +20,6 @@ import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.util.Locale;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -28,8 +27,6 @@ import java.util.function.Predicate;
import com.vaadin.data.util.BeanUtil;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.validator.BeanValidator;
-import com.vaadin.ui.Component;
-import com.vaadin.ui.UI;
/**
* A {@code Binder} subclass specialized for binding <em>beans</em>: classes
@@ -177,7 +174,7 @@ public class BeanBinder<BEAN> extends Binder<BEAN> {
if (BeanValidator.checkBeanValidationAvailable()) {
finalBinding = finalBinding.withValidator(new BeanValidator(
- getBinder().beanType, propertyName, getLocale()));
+ getBinder().beanType, propertyName, findLocale()));
}
PropertyDescriptor descriptor = getDescriptor(propertyName);
@@ -242,20 +239,6 @@ public class BeanBinder<BEAN> extends Binder<BEAN> {
throw new RuntimeException(exception);
});
}
-
- private Locale getLocale() {
- Locale l = null;
- if (getField() instanceof Component) {
- l = ((Component) getField()).getLocale();
- }
- if (l == null && UI.getCurrent() != null) {
- l = UI.getCurrent().getLocale();
- }
- if (l == null) {
- l = Locale.getDefault();
- }
- return l;
- }
}
private final Class<? extends BEAN> beanType;
diff --git a/server/src/main/java/com/vaadin/data/Binder.java b/server/src/main/java/com/vaadin/data/Binder.java
index 0a7e33c556..88549e12c3 100644
--- a/server/src/main/java/com/vaadin/data/Binder.java
+++ b/server/src/main/java/com/vaadin/data/Binder.java
@@ -38,7 +38,10 @@ import com.vaadin.server.ErrorMessage;
import com.vaadin.server.UserError;
import com.vaadin.shared.Registration;
import com.vaadin.ui.AbstractComponent;
+import com.vaadin.ui.AbstractSingleSelect;
+import com.vaadin.ui.Component;
import com.vaadin.ui.Label;
+import com.vaadin.ui.UI;
/**
* Connects one or more {@code Field} components to properties of a backing data
@@ -497,6 +500,25 @@ public class Binder<BEAN> implements Serializable {
}
}
+ /**
+ * Finds an appropriate locale to be used in conversion and validation.
+ *
+ * @return the found locale, not null
+ */
+ protected Locale findLocale() {
+ Locale l = null;
+ if (getField() instanceof Component) {
+ l = ((Component) getField()).getLocale();
+ }
+ if (l == null && UI.getCurrent() != null) {
+ l = UI.getCurrent().getLocale();
+ }
+ if (l == null) {
+ l = Locale.getDefault();
+ }
+ return l;
+ }
+
private void bind(BEAN bean) {
setFieldValue(bean);
onValueChange = getField()
@@ -521,7 +543,7 @@ public class Binder<BEAN> implements Serializable {
private ValidationStatus<TARGET> doValidation() {
FIELDVALUE fieldValue = field.getValue();
Result<TARGET> dataValue = converterValidatorChain.convertToModel(
- fieldValue, ((AbstractComponent) field).getLocale());
+ fieldValue, findLocale());
return new ValidationStatus<>(this, dataValue);
}
@@ -543,8 +565,7 @@ public class Binder<BEAN> implements Serializable {
private FIELDVALUE convertDataToFieldType(BEAN bean) {
return converterValidatorChain.convertToPresentation(
- getter.apply(bean),
- ((AbstractComponent) getField()).getLocale());
+ getter.apply(bean), findLocale());
}
/**
@@ -673,6 +694,8 @@ public class Binder<BEAN> implements Serializable {
* @param field
* the field to be bound, not null
* @return the new binding
+ *
+ * @see #bind(HasValue, Function, BiConsumer)
*/
public <FIELDVALUE> Binding<BEAN, FIELDVALUE, FIELDVALUE> forField(
HasValue<FIELDVALUE> field) {
@@ -686,6 +709,45 @@ public class Binder<BEAN> implements Serializable {
}
/**
+ * Creates a new binding for the given single select component. The returned
+ * binding may be further configured before invoking
+ * {@link Binding#bind(Function, BiConsumer) Binding.bind} which completes
+ * the binding. Until {@code Binding.bind} is called, the binding has no
+ * effect.
+ *
+ * @param <SELECTVALUE>
+ * the item type of the select
+ * @param select
+ * the select to be bound, not null
+ * @return the new binding
+ *
+ * @see #bind(AbstractSingleSelect, Function, BiConsumer)
+ */
+ public <SELECTVALUE> Binding<BEAN, SELECTVALUE, SELECTVALUE> forSelect(
+ AbstractSingleSelect<SELECTVALUE> select) {
+ return forField(new HasValue<SELECTVALUE>() {
+
+ @Override
+ public void setValue(SELECTVALUE value) {
+ select.setSelectedItem(value);
+ }
+
+ @Override
+ public SELECTVALUE getValue() {
+ return select.getSelectedItem().orElse(null);
+ }
+
+ @Override
+ public Registration addValueChangeListener(
+ ValueChangeListener<? super SELECTVALUE> listener) {
+ return select.addSelectionListener(e -> listener.accept(
+ new ValueChange<>(select, getValue(), e
+ .isUserOriginated())));
+ }
+ });
+ }
+
+ /**
* Binds a field to a bean property represented by the given getter and
* setter pair. The functions are used to update the field value from the
* property and to store the field value to the property, respectively.
@@ -735,6 +797,59 @@ public class Binder<BEAN> implements Serializable {
}
/**
+ * Binds a single select to a bean property represented by the given getter
+ * and setter pair. The functions are used to update the selection from the
+ * property and to store the selection to the property, respectively.
+ * <p>
+ * Use the {@link #forSelect(AbstractSingleSelect)} method instead if you
+ * want to further configure the new binding.
+ * <p>
+ * When a bean is bound with {@link Binder#bind(BEAN)}, the selected item is
+ * set to the return value of the given getter. The property value is then
+ * updated via the given setter whenever the selected item changes. The
+ * setter may be null; in that case the property value is never updated and
+ * the binding is said to be <i>read-only</i>. A null property value
+ * corresponds to no selection and vice versa.
+ * <p>
+ * If the Binder is already bound to some item, the newly bound select is
+ * associated with the corresponding bean property as described above.
+ * <p>
+ * The getter and setter can be arbitrary functions, for instance
+ * implementing user-defined conversion or validation. However, in the most
+ * basic use case you can simply pass a pair of method references to this
+ * method as follows:
+ *
+ * <pre>
+ * class Person {
+ * public enum Title { MR, MS, MISS, MRS, DR, PROF };
+ *
+ * public Title getTitle() { ... }
+ * public void setTitle(Title title) { ... }
+ * }
+ *
+ * NativeSelect<Title> titleSelect = new NativeSelect<>();
+ * titleSelect.setItems(Title.values());
+ * binder.bind(titleSelect, Person::getTitle, Person::setTitle);
+ * </pre>
+ *
+ * @param <SELECTVALUE>
+ * the item type of the select
+ * @param select
+ * the select to bind, not null
+ * @param getter
+ * the function to get the value of the property to the
+ * selection, not null
+ * @param setter
+ * the function to save the selection to the property or null if
+ * read-only
+ */
+ public <SELECTVALUE> void bind(AbstractSingleSelect<SELECTVALUE> select,
+ Function<BEAN, SELECTVALUE> getter,
+ BiConsumer<BEAN, SELECTVALUE> setter) {
+ forSelect(select).bind(getter, setter);
+ }
+
+ /**
* Binds the given bean to all the fields added to this Binder. To remove
* the binding, call {@link #unbind()}.
* <p>
diff --git a/server/src/main/java/com/vaadin/ui/AbstractSingleSelect.java b/server/src/main/java/com/vaadin/ui/AbstractSingleSelect.java
index 823650f443..81c22cffda 100644
--- a/server/src/main/java/com/vaadin/ui/AbstractSingleSelect.java
+++ b/server/src/main/java/com/vaadin/ui/AbstractSingleSelect.java
@@ -254,6 +254,17 @@ public abstract class AbstractSingleSelect<T> extends
return getSelectionModel().getSelectedItem();
}
+ /**
+ * Sets the current selection to the given item or clears selection if given
+ * {@code null}.
+ *
+ * @param item
+ * the item to select or {@code null} to clear selection
+ */
+ public void setSelectedItem(T item) {
+ getSelectionModel().setSelectedItem(item);
+ }
+
@Override
protected AbstractSingleSelectState getState() {
return (AbstractSingleSelectState) super.getState();