瀏覽代碼

Binding.validate() should fire a validation status event (#134).

Change-Id: I2121ec8f90ffcdf2fdfa02bf99084b539b27180e
tags/8.0.0.alpha1
Denis Anisimov 7 年之前
父節點
當前提交
78c6ab1852

+ 2
- 2
server/src/main/java/com/vaadin/data/Binder.java 查看文件

@@ -485,6 +485,7 @@ public class Binder<BEAN> implements Serializable {
FIELDVALUE fieldValue = field.getValue();
Result<TARGET> dataValue = converterValidatorChain.convertToModel(
fieldValue, ((AbstractComponent) field).getLocale());
fireStatusChangeEvent(dataValue);
return dataValue;
}

@@ -554,7 +555,7 @@ public class Binder<BEAN> implements Serializable {
return newBinding;
}

private void fireStatusChangeEvent(Result<?> result) {
private void fireStatusChangeEvent(Result<TARGET> result) {
ValidationStatusChangeEvent event = new ValidationStatusChangeEvent(
getField(),
result.isError() ? ValidationStatus.ERROR
@@ -716,7 +717,6 @@ public class Binder<BEAN> implements Serializable {
List<ValidationError<?>> resultErrors = new ArrayList<>();
for (BindingImpl<BEAN, ?, ?> binding : bindings) {
Result<?> result = binding.validate();
binding.fireStatusChangeEvent(result);
result.ifError(errorMessage -> resultErrors
.add(new ValidationError<>(binding.field, errorMessage)));
}

+ 51
- 1
server/src/test/java/com/vaadin/data/BinderBookOfVaadinTest.java 查看文件

@@ -256,7 +256,7 @@ public class BinderBookOfVaadinTest {
}

@Test
public void crossFieldValidation() {
public void crossFieldValidation_validateUsingBinder() {
Binder<Trip> binder = new Binder<>();
PopupDateField departing = new PopupDateField("Departing");
PopupDateField returning = new PopupDateField("Returning");
@@ -310,6 +310,56 @@ public class BinderBookOfVaadinTest {

}

@Test
public void crossFieldValidation_validateUsingBinding() {
Binder<Trip> binder = new Binder<>();
PopupDateField departing = new PopupDateField("Departing");
PopupDateField returning = new PopupDateField("Returning");

Binding<Trip, Date, Date> returnBinding = binder.forField(returning)
.withValidator(
returnDate -> !returnDate.before(departing.getValue()),
"Cannot return before departing");

returnBinding.bind(Trip::getReturnDate, Trip::setReturnDate);
departing.addValueChangeListener(event -> returnBinding.validate());

Calendar calendar = Calendar.getInstance();
Date past = calendar.getTime();
calendar.add(1, Calendar.DAY_OF_YEAR);
Date before = calendar.getTime();
calendar.add(1, Calendar.DAY_OF_YEAR);
Date after = calendar.getTime();

departing.setValue(before);
returning.setValue(after);

Result<Date> result = returnBinding.validate();
Assert.assertFalse(result.isError());
Assert.assertNull(departing.getComponentError());

// update returning => validation is done against this field
returning.setValue(past);
result = returnBinding.validate();

Assert.assertTrue(result.isError());
Assert.assertNotNull(returning.getComponentError());

// set correct value back
returning.setValue(before);
result = returnBinding.validate();

Assert.assertFalse(result.isError());
Assert.assertNull(departing.getComponentError());

// update departing => validation is done because of listener added
departing.setValue(after);
result = returnBinding.validate();

Assert.assertTrue(result.isError());
Assert.assertNotNull(returning.getComponentError());
}

@Test
public void withStatusLabelExample() {
Label emailStatus = new Label();

+ 66
- 0
server/src/test/java/com/vaadin/data/BinderTest.java 查看文件

@@ -460,6 +460,25 @@ public class BinderTest {
Assert.assertNull(nameField.getComponentError());
}

@Test
public void bindingWithStatusChangeHandler_defaultStatusChangeHandlerIsReplaced() {
Binding<Person, String, String> binding = binder.forField(nameField)
.withValidator(notEmpty).withStatusChangeHandler(evt -> {
});
binding.bind(Person::getFirstName, Person::setLastName);

Assert.assertNull(nameField.getComponentError());

nameField.setValue("");

// First validation fails => should be event with ERROR status and
// message
binding.validate();

// default behavior should update component error for the nameField
Assert.assertNull(nameField.getComponentError());
}

@Test
public void withStatusLabel_labelIsUpdatedAccordingStatus() {
Label label = new Label();
@@ -487,6 +506,33 @@ public class BinderTest {
Assert.assertEquals("", label.getValue());
}

@Test
public void bindingWithStatusLabel_labelIsUpdatedAccordingStatus() {
Label label = new Label();

Binding<Person, String, String> binding = binder.forField(nameField)
.withValidator(notEmpty).withStatusLabel(label);
binding.bind(Person::getFirstName, Person::setLastName);

nameField.setValue("");

// First validation fails => should be event with ERROR status and
// message
binding.validate();

Assert.assertTrue(label.isVisible());
Assert.assertEquals("Value cannot be empty", label.getValue());

nameField.setValue("foo");

// Second validation succeeds => should be event with OK status and
// no message
binding.validate();

Assert.assertFalse(label.isVisible());
Assert.assertEquals("", label.getValue());
}

@Test
public void withStatusLabel_defaultStatusChangeHandlerIsReplaced() {
Label label = new Label();
@@ -507,6 +553,26 @@ public class BinderTest {
Assert.assertNull(nameField.getComponentError());
}

@Test
public void bindingWithStatusLabel_defaultStatusChangeHandlerIsReplaced() {
Label label = new Label();

Binding<Person, String, String> binding = binder.forField(nameField)
.withValidator(notEmpty).withStatusLabel(label);
binding.bind(Person::getFirstName, Person::setLastName);

Assert.assertNull(nameField.getComponentError());

nameField.setValue("");

// First validation fails => should be event with ERROR status and
// message
binding.validate();

// default behavior should update component error for the nameField
Assert.assertNull(nameField.getComponentError());
}

@Test(expected = IllegalStateException.class)
public void withStatusChangeHandler_addAfterBound() {
Binding<Person, String, String> binding = binder.forField(nameField)

Loading…
取消
儲存