Browse Source

Added method asRequired with a custom required validator to BindingBuilder. (#10724)

tags/8.4.0.alpha1
Márcio P. Dantas 6 years ago
parent
commit
3c52491a5b

+ 27
- 3
server/src/main/java/com/vaadin/data/Binder.java View File

@@ -728,6 +728,23 @@ public class Binder<BEAN> implements Serializable {
*/
public BindingBuilder<BEAN, TARGET> asRequired(
ErrorMessageProvider errorMessageProvider);

/**
* Sets the field to be required and delegates the required check to a custom validator.
* This means two things:
* <ol>
* <li>the required indicator will be displayed for this field</li>
* <li>the field value is validated by customRequiredValidator</li>
* </ol>
*
* @see HasValue#setRequiredIndicatorVisible(boolean)
* @param customRequiredValidator
* validator responsible for the required check
* @return this binding, for chaining
* @since
*/
public BindingBuilder<BEAN, TARGET> asRequired(
Validator<TARGET> customRequiredValidator);
}

/**
@@ -885,11 +902,18 @@ public class Binder<BEAN> implements Serializable {
@Override
public BindingBuilder<BEAN, TARGET> asRequired(
ErrorMessageProvider errorMessageProvider) {
return asRequired(
Validator.from(
value -> !Objects.equals(value, field.getEmptyValue()),
errorMessageProvider));
}

@Override
public BindingBuilder<BEAN, TARGET> asRequired(
Validator<TARGET> customRequiredValidator) {
checkUnbound();
field.setRequiredIndicatorVisible(true);
return withValidator(
value -> !Objects.equals(value, field.getEmptyValue()),
errorMessageProvider);
return withValidator(customRequiredValidator);
}

/**

+ 92
- 0
server/src/test/java/com/vaadin/data/BinderTest.java View File

@@ -30,6 +30,7 @@ import com.vaadin.shared.ui.ErrorLevel;
import com.vaadin.tests.data.bean.Person;
import com.vaadin.tests.data.bean.Sex;
import com.vaadin.ui.TextField;
import org.apache.commons.lang.StringUtils;

public class BinderTest extends BinderTestBase<Binder<Person>, Person> {

@@ -501,6 +502,97 @@ public class BinderTest extends BinderTestBase<Binder<Person>, Person> {
assertTrue(textField.isRequiredIndicatorVisible());
}

@Test
public void setRequired_withCustomValidator_fieldGetsRequiredIndicatorAndValidator() {
TextField textField = new TextField();
textField.setLocale(Locale.CANADA);
assertFalse(textField.isRequiredIndicatorVisible());

BindingBuilder<Person, String> binding = binder.forField(textField);
assertFalse(textField.isRequiredIndicatorVisible());
AtomicInteger invokes = new AtomicInteger();

Validator<String> customRequiredValidator = (value, context) -> {
invokes.incrementAndGet();
if (StringUtils.isBlank(value)) {
return ValidationResult.error("Input is required.");
}
return ValidationResult.ok();
};
binding.asRequired(customRequiredValidator);
assertTrue(textField.isRequiredIndicatorVisible());

binding.bind(Person::getFirstName, Person::setFirstName);
binder.setBean(item);
assertNull(textField.getErrorMessage());
assertEquals(0, invokes.get());

textField.setValue(" ");
ErrorMessage errorMessage = textField.getErrorMessage();
assertNotNull(errorMessage);
assertEquals("Input&#32;is&#32;required&#46;", errorMessage.getFormattedHtmlMessage());
// validation is done for all changed bindings once.
assertEquals(1, invokes.get());

textField.setValue("value");
assertNull(textField.getErrorMessage());
assertTrue(textField.isRequiredIndicatorVisible());
}

@Test
public void setRequired_withCustomValidator_modelConverterBeforeValidator() {
TextField textField = new TextField();
textField.setLocale(Locale.CANADA);
assertFalse(textField.isRequiredIndicatorVisible());

Converter<String, String> stringBasicPreProcessingConverter = new Converter<String, String>() {
@Override
public Result<String> convertToModel(String value, ValueContext context) {
if (StringUtils.isBlank(value)) {
return Result.ok(null);
}
return Result.ok(StringUtils.trim(value));
}

@Override
public String convertToPresentation(String value, ValueContext context) {
if (value == null) {
return "";
}
return value;
}
};

AtomicInteger invokes = new AtomicInteger();
Validator<String> customRequiredValidator = (value, context) -> {
invokes.incrementAndGet();
if (value == null) {
return ValidationResult.error("Input required.");
}
return ValidationResult.ok();
};

binder.forField(textField)
.withConverter(stringBasicPreProcessingConverter)
.asRequired(customRequiredValidator)
.bind(Person::getFirstName, Person::setFirstName);

binder.setBean(item);
assertNull(textField.getErrorMessage());
assertEquals(0, invokes.get());

textField.setValue(" ");
ErrorMessage errorMessage = textField.getErrorMessage();
assertNotNull(errorMessage);
assertEquals("Input&#32;required&#46;", errorMessage.getFormattedHtmlMessage());
// validation is done for all changed bindings once.
assertEquals(1, invokes.get());

textField.setValue("value");
assertNull(textField.getErrorMessage());
assertTrue(textField.isRequiredIndicatorVisible());
}

@Test
public void validationStatusHandler_onlyRunForChangedField() {
TextField firstNameField = new TextField();

Loading…
Cancel
Save