json-schema-form / angular-schema-form

Generate forms from a JSON schema, with AngularJS!
https://json-schema-form.github.io/angular-schema-form
MIT License
2.47k stars 653 forks source link

fix for #888 - array validation broken in angular 1.5.10 #998

Closed alambir closed 1 year ago

alambir commented 4 years ago

Description

This fixes issue #888. On angular 1.5.10+, firstDigest value is false on the initial load which triggers validation on empty fields. There might be some changes in the digest cycle/processing between angular v1.5.9 and v1.5.10+

firstDigest is initialised in sf-schema-directive.js

        // We need to know if we're in the first digest looping
        // I.e. just rendered the form so we know not to validate
        // empty fields.
        childScope.firstDigest = true;
        // We use a ordinary timeout since we don't need a digest after this.
        setTimeout(function() {
          childScope.firstDigest = false;
          scope.$apply();
        }, 0);

and consumed in sf-array-directive.js in the following block:

      // We need to have a ngModel to hook into validation. It doesn't really play well with
      // arrays though so we both need to trigger validation and onChange.
      // So we watch the value as well. But watching an array can be tricky. We wan't to know
      // when it changes so we can validate,
      let watchFn = function() {
        // scope.modelArray = modelArray;
        scope.modelArray = scope.$eval(attrs.sfNewArray);
        // validateField method is exported by schema-validate
        if (scope.ngModel && scope.ngModel.$pristine && scope.firstDigest &&
            (!scope.options || scope.options.validateOnRender !== true)) {
          return;
        }
        else if (scope.validateField) {
          scope.validateField();
        }
      };

Tests were carried on angular 1.5.9 and 1.5.10 to check the $pristine value of the field (schema-validatate-directive.js):

        ngModel.$formatters.push(function(val) {
        // When a form first loads this will be called for each field.
        // we usually don't want that.
        if (ngModel.$pristine && first &&
            (!scope.options || scope.options.validateOnRender !== true)) {
          first = false; 
          return val;
        }
        validate(ngModel.$modelValue);
        return val;
      });

Angular 1.5.9

initial load page:
ngModel.$pristine true

click on yes radio button:
ngModel.$pristine true
ngModel.$pristine true
ngModel.$pristine true
ngModel.$pristine true

Angular 1.5.10

initial load page:
ngModel.$pristine true

click on yes radio button:
ngModel.$pristine true
ngModel.$pristine true
ngModel.$pristine false <----
ngModel.$pristine true

Removing scope.firstDigest from the condition in (watchFn function - sf-array-directive.js) line 22 fixes this issue.

Checklist

@json-schema-form/angular-schema-form-lead

ivarprudnikov commented 4 years ago

Diff between AngularJS 1.5.9 and 1.5.10 https://github.com/angular/angular.js/compare/v1.5.9...v1.5.10

john-latham commented 1 year ago

This PR appears to include private code changes. It should not be merged.