Skip to content

Commit

Permalink
feat: allow disabling validation status change listener registration …
Browse files Browse the repository at this point in the history
…on binder (#14205)

Add binder-level flag to allow disabling of
validation status change listener registration
for HasValidator fields.

Related to #13940 (comment) and vaadin/flow-components#3406 (comment)

(cherry picked from commit 420498c)

Co-authored-by: Knoobie <knoobie@gmx.de>
  • Loading branch information
taefi and knoobie committed Jul 22, 2022
1 parent 89e0d9e commit 4b0834f
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 11 deletions.
50 changes: 39 additions & 11 deletions flow-data/src/main/java/com/vaadin/flow/data/binder/Binder.java
Expand Up @@ -940,8 +940,8 @@ public BindingBuilder<BEAN, TARGET> withValidator(
Objects.requireNonNull(validator, "validator cannot be null");

Validator<? super TARGET> wrappedValidator = ((value, context) -> {
if (getBinder().isValidatorsDisabled() ||
(binding != null && binding.isValidatorsDisabled())) {
if (getBinder().isValidatorsDisabled() || (binding != null
&& binding.isValidatorsDisabled())) {
return ValidationResult.ok();
} else {
return validator.apply(value, context);
Expand Down Expand Up @@ -1121,7 +1121,8 @@ public BindingImpl(BindingBuilderImpl<BEAN, FIELDVALUE, TARGET> builder,
onValueChange = getField().addValueChangeListener(
event -> handleFieldValueChange(event));

if (getField() instanceof HasValidator) {
if (getBinder().isFieldsValidationStatusChangeListenerEnabled()
&& getField() instanceof HasValidator) {
HasValidator<FIELDVALUE> hasValidatorField = (HasValidator<FIELDVALUE>) getField();
onValidationStatusChange = hasValidatorField
.addValidationStatusChangeListener(
Expand Down Expand Up @@ -1425,7 +1426,8 @@ public boolean isValidatorsDisabled() {
}

@Override
public void setConvertBackToPresentation(boolean convertBackToPresentation) {
public void setConvertBackToPresentation(
boolean convertBackToPresentation) {
this.convertBackToPresentation = convertBackToPresentation;
}

Expand Down Expand Up @@ -1543,6 +1545,8 @@ void setIdentity() {

private boolean validatorsDisabled = false;

private boolean fieldsValidationStatusChangeListenerEnabled = true;

/**
* Creates a binder using a custom {@link PropertySet} implementation for
* finding and resolving property names for
Expand Down Expand Up @@ -1961,7 +1965,7 @@ public void writeBean(BEAN bean) throws ValidationException {
* {@code null}
*/
public void writeBeanAsDraft(BEAN bean) {
doWriteDraft(bean, new ArrayList<>(bindings),false);
doWriteDraft(bean, new ArrayList<>(bindings), false);
}

/**
Expand All @@ -1981,7 +1985,7 @@ public void writeBeanAsDraft(BEAN bean) {
* disable all Validators during write
*/
public void writeBeanAsDraft(BEAN bean, boolean forced) {
doWriteDraft(bean, new ArrayList<>(bindings),forced);
doWriteDraft(bean, new ArrayList<>(bindings), forced);
}

/**
Expand Down Expand Up @@ -2090,12 +2094,12 @@ private BinderValidationStatus<BEAN> doWriteIfValid(BEAN bean,
* disable validators during write if true
*/
@SuppressWarnings({ "unchecked" })
private void doWriteDraft(BEAN bean,
Collection<Binding<BEAN, ?>> bindings, boolean forced) {
private void doWriteDraft(BEAN bean, Collection<Binding<BEAN, ?>> bindings,
boolean forced) {
Objects.requireNonNull(bean, "bean cannot be null");

if (!forced) {
bindings.forEach(binding -> ((BindingImpl<BEAN, ?, ?>) binding)
bindings.forEach(binding -> ((BindingImpl<BEAN, ?, ?>) binding)
.writeFieldValue(bean));
} else {
boolean isDisabled = isValidatorsDisabled();
Expand Down Expand Up @@ -3202,7 +3206,7 @@ public void removeBinding(String propertyName) {
/**
* Control whether validators including bean level validators are
* disabled or enabled globally for this Binder.
*
*
* @param validatorsDisabled Boolean value.
*/
public void setValidatorsDisabled(boolean validatorsDisabled) {
Expand All @@ -3212,10 +3216,34 @@ public void setValidatorsDisabled(boolean validatorsDisabled) {
/**
* Returns if the validators including bean level validators
* are disabled or enabled for this Binder.
*
*
* @return Boolean value
*/
public boolean isValidatorsDisabled() {
return validatorsDisabled;
}

/**
* Control whether bound fields implementing {@link HasValidator} subscribe
* for field's {@code ValidationStatusChangeEvent}s and will
* {@code validate} upon receiving them.
*
* @param fieldsValidationStatusChangeListenerEnabled
* Boolean value.
*/
public void setFieldsValidationStatusChangeListenerEnabled(
boolean fieldsValidationStatusChangeListenerEnabled) {
this.fieldsValidationStatusChangeListenerEnabled = fieldsValidationStatusChangeListenerEnabled;
}

/**
* Returns if the bound fields implementing {@link HasValidator} subscribe
* for field's {@code ValidationStatusChangeEvent}s and will
* {@code validate} upon receiving them.
*
* @return Boolean value
*/
public boolean isFieldsValidationStatusChangeListenerEnabled() {
return fieldsValidationStatusChangeListenerEnabled;
}
}
Expand Up @@ -64,6 +64,16 @@ public void fieldWithHasValidatorDefaults_bindIsCalled_addValidationStatusListen
.addValidationStatusChangeListener(Mockito.any());
}

@Test
public void binderWithFieldsValidationStatusChangeListenerDisabled_bindIsCalled_noValidationStatusListenerIsCalled() {
binder.setFieldsValidationStatusChangeListenerEnabled(false);
TestHasValidatorDatePicker.DatePickerHasValidatorDefaults field = Mockito
.spy(TestHasValidatorDatePicker.DatePickerHasValidatorDefaults.class);
binder.bind(field, BIRTH_DATE_PROPERTY);
Mockito.verify(field, Mockito.never())
.addValidationStatusChangeListener(Mockito.any());
}

@Test
public void fieldWithHasValidatorOnlyGetDefaultValidatorOverridden_bindIsCalled_addValidationStatusListenerIsCalled() {
TestHasValidatorDatePicker.DataPickerHasValidatorGetDefaultValidatorOverridden field = Mockito
Expand Down Expand Up @@ -102,6 +112,17 @@ public void fieldWithHasValidatorFullyOverridden_fieldValidationStatusChangesToF
Assert.assertEquals(INVALID_DATE_FORMAT, componentErrors.get(field));
}

@Test
public void binderWithFieldsValidationStatusChangeListenerDisabled_fieldValidationStatusChangesToFalse_binderHandleErrorIsNotCalled() {
binder.setFieldsValidationStatusChangeListenerEnabled(false);
TestHasValidatorDatePicker.DataPickerHasValidatorOverridden field = new TestHasValidatorDatePicker.DataPickerHasValidatorOverridden();
binder.bind(field, BIRTH_DATE_PROPERTY);
Assert.assertEquals(0, componentErrors.size());

field.fireValidationStatusChangeEvent(false);
Assert.assertEquals(0, componentErrors.size());
}

@Test
public void fieldWithHasValidatorFullyOverridden_fieldValidationStatusChangesToTrue_binderClearErrorIsCalled() {
TestHasValidatorDatePicker.DataPickerHasValidatorOverridden field = new TestHasValidatorDatePicker.DataPickerHasValidatorOverridden();
Expand Down

0 comments on commit 4b0834f

Please sign in to comment.