@@ -1920,10 +1920,24 @@ public static <BEAN> Binder<BEAN> withPropertySet(
1920
1920
*/
1921
1921
protected void handleFieldValueChange (Binding <BEAN , ?> binding ) {
1922
1922
changedBindings .add (binding );
1923
- if (getBean () != null ) {
1924
- doWriteIfValid (getBean (), changedBindings );
1923
+
1924
+ if (getBean () == null ) {
1925
+ binding .validate ();
1925
1926
} else {
1926
- validate (binding );
1927
+ BinderValidationStatus <BEAN > status = validateBindingsAndBean ();
1928
+ if (status .isOk ()) {
1929
+ doWriteIfValid (getBean (), changedBindings );
1930
+ } else {
1931
+ // Fire status change for changed bindings only
1932
+ getValidationStatusHandler ()
1933
+ .statusChange (new BinderValidationStatus <>(this ,
1934
+ status .getFieldValidationStatuses ().stream ()
1935
+ .filter (s -> changedBindings
1936
+ .contains (s .getBinding ()))
1937
+ .collect (Collectors .toList ()),
1938
+ status .getBeanValidationErrors ()));
1939
+ fireStatusChangeEvent (status .hasErrors ());
1940
+ }
1927
1941
}
1928
1942
}
1929
1943
@@ -2512,9 +2526,10 @@ private BinderValidationStatus<BEAN> doWriteIfValid(BEAN bean,
2512
2526
bindings );
2513
2527
2514
2528
// First run fields level validation, if no validation errors then
2515
- // update bean. Note that this will validate all bindings.
2516
- List <BindingValidationStatus <?>> bindingResults = getBindings ().stream ()
2517
- .map (b -> b .validate (false )).collect (Collectors .toList ());
2529
+ // update bean.
2530
+ List <BindingValidationStatus <?>> bindingResults = currentBindings
2531
+ .stream ().map (b -> b .validate (false ))
2532
+ .collect (Collectors .toList ());
2518
2533
2519
2534
if (bindingResults .stream ()
2520
2535
.noneMatch (BindingValidationStatus ::isError )) {
@@ -2781,35 +2796,25 @@ protected BinderValidationStatus<BEAN> validate(boolean fireEvent) {
2781
2796
}
2782
2797
2783
2798
/**
2784
- * Validates the target binding. Also runs validation for all other
2785
- * bindings, and if possible, bean-level validations as well.
2799
+ * Runs validation for all bindings to determine binder's validity state. If
2800
+ * a bean has been set and all bindings pass validation, bean-level
2801
+ * validations are run as well.
2786
2802
*
2787
- * {@link BinderValidationStatusHandler} is called with only the status of
2788
- * the target binding.
2789
- *
2790
- * {@link StatusChangeEvent} is fired with current binder validation status
2791
- *
2792
- * @param targetBinding
2793
- * target binding for validation
2803
+ * @return BinderValidationStatus for the validation run
2794
2804
*/
2795
- private void validate (Binding <BEAN , ?> targetBinding ) {
2796
- List <BindingValidationStatus <?>> bindingValidationStatuses = validateBindings ();
2805
+ private BinderValidationStatus <BEAN > validateBindingsAndBean () {
2806
+ List <BindingValidationStatus <?>> bindingStatuses = validateBindings ();
2807
+ boolean bindingsInError = bindingStatuses .stream ()
2808
+ .anyMatch (BindingValidationStatus ::isError );
2797
2809
2798
2810
List <ValidationResult > beanStatuses = new ArrayList <>();
2799
- if (getBean () != null ) {
2811
+ // Only execute bean-level validation when binding validators pass
2812
+ if (!bindingsInError ) {
2800
2813
beanStatuses .addAll (validateBean (getBean ()));
2801
2814
}
2802
- BindingValidationStatus <?> status = bindingValidationStatuses .stream ()
2803
- .filter (s -> targetBinding .equals (s .getBinding ())).findFirst ()
2804
- .orElse (null );
2805
-
2806
- getValidationStatusHandler ().statusChange (new BinderValidationStatus <>(
2807
- this , Collections .singletonList (status ),
2808
- Collections .emptyList ()));
2809
2815
2810
- fireStatusChangeEvent (bindingValidationStatuses .stream ()
2811
- .anyMatch (BindingValidationStatus ::isError )
2812
- || beanStatuses .stream ().anyMatch (ValidationResult ::isError ));
2816
+ return new BinderValidationStatus <>(this , bindingStatuses ,
2817
+ beanStatuses );
2813
2818
}
2814
2819
2815
2820
/**
0 commit comments