Kaynağa Gözat

Add API for running BindingValidationStatusHandlers (#9966)

This patch adds an API to Binding for accessing the validation status handlers from a custom BinderValidationStatusHandler.
tags/8.2.0.alpha2
Teemu Suo-Anttila 6 yıl önce
ebeveyn
işleme
1f59cb51af

+ 13
- 6
server/src/main/java/com/vaadin/data/Binder.java Dosyayı Görüntüle

@@ -126,6 +126,15 @@ public class Binder<BEAN> implements Serializable {
*/
public BindingValidationStatus<TARGET> validate();

/**
* Gets the validation status handler for this Binding.
*
* @return the validation status handler for this binding
*
* @since 8.2
*/
public BindingValidationStatusHandler getValidationStatusHandler();

/**
* Unbinds the binding from its respective {@code Binder}
* Removes any {@code ValueChangeListener} {@code Registration} from
@@ -134,7 +143,6 @@ public class Binder<BEAN> implements Serializable {
* @since 8.2
*/
public void unbind();

}

/**
@@ -990,8 +998,9 @@ public class Binder<BEAN> implements Serializable {
return binder;
}

private void notifyStatusHandler(BindingValidationStatus<?> status) {
statusHandler.statusChange(status);
@Override
public BindingValidationStatusHandler getValidationStatusHandler() {
return statusHandler;
}
}

@@ -1948,9 +1957,7 @@ public class Binder<BEAN> implements Serializable {
protected void handleBinderValidationStatus(
BinderValidationStatus<BEAN> binderStatus) {
// let field events go to binding status handlers
binderStatus.getFieldValidationStatuses()
.forEach(status -> ((BindingImpl<?, ?, ?>) status.getBinding())
.notifyStatusHandler(status));
binderStatus.notifyBindingValidationStatusHandlers();

// show first possible error or OK status in the label if set
if (getStatusLabel().isPresent()) {

+ 33
- 2
server/src/main/java/com/vaadin/data/BinderValidationStatus.java Dosyayı Görüntüle

@@ -23,6 +23,7 @@ import java.util.Objects;
import java.util.stream.Collectors;

import com.vaadin.data.Binder.BindingBuilder;
import com.vaadin.server.SerializablePredicate;

/**
* Binder validation status change. Represents the outcome of binder level
@@ -33,8 +34,8 @@ import com.vaadin.data.Binder.BindingBuilder;
* Note: if there are any field level validation errors, the bean level
* validation is not run.
* <p>
* Use {@link Binder#setValidationStatusHandler(BinderValidationStatusHandler)} to handle
* form level validation status changes.
* Use {@link Binder#setValidationStatusHandler(BinderValidationStatusHandler)}
* to handle form level validation status changes.
*
* @author Vaadin Ltd
*
@@ -188,4 +189,34 @@ public class BinderValidationStatus<BEAN> implements Serializable {
return binderStatuses.stream().filter(ValidationResult::isError)
.collect(Collectors.toList());
}

/**
* Notifies all validation status handlers in bindings.
*
* @see #notifyBindingValidationStatusHandlers(SerializablePredicate)
*
* @since 8.2
*/
public void notifyBindingValidationStatusHandlers() {
notifyBindingValidationStatusHandlers(t -> true);
}

/**
* Notifies validation status handlers for bindings that pass given filter.
* The filter should return {@code true} for each
* {@link BindingValidationStatus} that should be delegated to the status
* handler in the binding.
*
* @see #notifyBindingValidationStatusHandlers()
*
* @param filter
* the filter to select bindings to run status handling for
*
* @since 8.2
*/
public void notifyBindingValidationStatusHandlers(
SerializablePredicate<BindingValidationStatus<?>> filter) {
bindingStatuses.stream().filter(filter).forEach(s -> s.getBinding()
.getValidationStatusHandler().statusChange(s));
}
}

+ 3
- 3
server/src/main/java/com/vaadin/data/BinderValidationStatusHandler.java Dosyayı Görüntüle

@@ -21,8 +21,9 @@ import com.vaadin.ui.AbstractComponent;
/**
* Handler for {@link BinderValidationStatus} changes.
* <p>
* {@link Binder#setValidationStatusHandler(BinderValidationStatusHandler) Register} an
* instance of this class to be able to customize validation status handling.
* {@link Binder#setValidationStatusHandler(BinderValidationStatusHandler)
* Register} an instance of this class to be able to customize validation status
* handling.
* <p>
* The default handler will show
* {@link AbstractComponent#setComponentError(com.vaadin.server.ErrorMessage) an
@@ -53,5 +54,4 @@ public interface BinderValidationStatusHandler<BEAN>
* the changed status
*/
void statusChange(BinderValidationStatus<BEAN> statusChange);

}

+ 62
- 1
server/src/test/java/com/vaadin/data/BinderTest.java Dosyayı Görüntüle

@@ -749,6 +749,68 @@ public class BinderTest extends BinderTestBase<Binder<Person>, Person> {
String.valueOf(item.getAge()), ageField.getValue());
}

static class MyBindingHandler implements BindingValidationStatusHandler {

boolean expectingError = false;
int callCount = 0;

@Override
public void statusChange(BindingValidationStatus<?> statusChange) {
++callCount;
if (expectingError) {
Assert.assertTrue("Expecting error", statusChange.isError());
} else {
Assert.assertFalse("Unexpected error", statusChange.isError());
}
}
}

@Test
public void execute_binding_status_handler_from_binder_status_handler() {
MyBindingHandler bindingHandler = new MyBindingHandler();
binder.forField(nameField)
.withValidator(t -> !t.isEmpty(), "No empty values.")
.withValidationStatusHandler(bindingHandler)
.bind(Person::getFirstName, Person::setFirstName);

String ageError = "CONVERSIONERROR";
binder.forField(ageField)
.withConverter(new StringToIntegerConverter(ageError))
.bind(Person::getAge, Person::setAge);

binder.setValidationStatusHandler(status -> {
status.notifyBindingValidationStatusHandlers();
});

String initialName = item.getFirstName();
int initialAge = item.getAge();

binder.setBean(item);

// Test specific error handling.
bindingHandler.expectingError = true;
nameField.setValue("");

// Test default error handling.
ageField.setValue("foo");
Assert.assertTrue("Component error does not contain error message",
ageField.getComponentError().getFormattedHtmlMessage()
.contains(ageError));

// Restore values and test no errors.
ageField.setValue(String.valueOf(initialAge));
Assert.assertNull("There should be no component error",
ageField.getComponentError());

bindingHandler.expectingError = false;
nameField.setValue(initialName);

// Assert that the handler was called.
Assert.assertEquals(
"Unexpected callCount to binding validation status handler", 4,
bindingHandler.callCount);
}
@Test
public void removed_binding_not_updates_value() {
Binding<Person, Integer> binding = binder.forField(ageField)
@@ -766,6 +828,5 @@ public class BinderTest extends BinderTestBase<Binder<Person>, Person> {

Assert.assertEquals("Binding still affects bean even after unbind",
ageBeforeUnbind, String.valueOf(item.getAge()));

}
}

Loading…
İptal
Kaydet