Code coverage report for src/directives/schema-validate.js

Statements: 54.39% (31 / 57)      Branches: 35.29% (12 / 34)      Functions: 53.33% (8 / 15)      Lines: 53.57% (30 / 56)      Ignored: none     

All files » src/directives/ » schema-validate.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 1621     50                     150   150 150   150                         150     2         2       2       2 2     2   2 2           2 2                   150       150 450             150   300                 150       150 150     164       150     150                                                                                     150   150            
angular.module('schemaForm').directive('schemaValidate', ['sfValidator', '$parse', 'sfSelect',
  function(sfValidator, $parse, sfSelect) {
 
    return {
      restrict: 'A',
      scope: false,
      // We want the link function to be *after* the input directives link function so we get access
      // the parsed value, ex. a number instead of a string
      priority: 500,
      require: 'ngModel',
      link: function(scope, element, attrs, ngModel) {
        // We need the ngModelController on several places,
        // most notably for errors.
        // So we emit it up to the decorator directive so it can put it on scope.
        scope.$emit('schemaFormPropagateNgModelController', ngModel);
 
        var error = null;
        var form = scope.$eval(attrs.schemaValidate);
 
        Iif (form.copyValueTo) {
          ngModel.$viewChangeListeners.push(function() {
            var paths = form.copyValueTo;
            angular.forEach(paths, function(path) {
              sfSelect(path, scope.model, ngModel.$modelValue);
            });
          });
        }
 
 
 
        // Validate against the schema.
 
        var validate = function(viewValue) {
          //console.log('validate called', viewValue)
          //Still might be undefined
          Iif (!form) {
            return viewValue;
          }
 
          // Omit TV4 validation
          Iif (scope.options && scope.options.tv4Validation === false) {
            return viewValue;
          }
 
          var result =  sfValidator.validate(form, viewValue);
          //console.log('result is', result)
          // Since we might have different tv4 errors we must clear all
          // errors that start with tv4-
          Object.keys(ngModel.$error)
              .filter(function(k) { return k.indexOf('tv4-') === 0; })
              .forEach(function(k) { ngModel.$setValidity(k, true); });
 
          Eif (!result.valid) {
            // it is invalid, return undefined (no model update)
            ngModel.$setValidity('tv4-' + result.error.code, false);
            error = result.error;
 
            // In Angular 1.3+ return the viewValue, otherwise we inadvertenly
            // will trigger a 'parse' error.
            // we will stop the model value from updating with our own $validator
            // later.
            Eif (ngModel.$validators) {
              return viewValue;
            }
            // Angular 1.2 on the other hand lacks $validators and don't add a 'parse' error.
            return undefined;
          }
          console.log(ngModel)
          return viewValue;
        };
 
        // Custom validators, parsers, formatters etc
        Iif (typeof form.ngModel === 'function') {
          form.ngModel(ngModel);
        }
 
        ['$parsers', '$viewChangeListeners', '$formatters'].forEach(function(attr) {
          Iif (form[attr] && ngModel[attr]) {
            form[attr].forEach(function(fn) {
              ngModel[attr].push(fn);
            });
          }
        });
 
        ['$validators', '$asyncValidators'].forEach(function(attr) {
          // Check if our version of angular has validators, i.e. 1.3+
          Iif (form[attr] && ngModel[attr]) {
            angular.forEach(form[attr], function(fn, name) {
              ngModel[attr][name] = fn;
            });
          }
        });
 
        // Get in last of the parses so the parsed value has the correct type.
        // We don't use $validators since we like to set different errors depending tv4 error codes
        ngModel.$parsers.push(validate);
 
        // But we do use one custom validator in the case of Angular 1.3 to stop the model from
        // updating if we've found an error.
        Eif (ngModel.$validators) {
          ngModel.$validators.schemaForm = function() {
            //console.log('validators called.')
            // Any error and we're out of here!
            return !Object.keys(ngModel.$error).some(function(e) { return e !== 'schemaForm';});
          };
        }
 
        var schema = form.schema;
 
        // A bit ugly but useful.
        scope.validateField =  function() {
 
          // Special case: arrays
          // TODO: Can this be generalized in a way that works consistently?
          // Just setting the viewValue isn't enough to trigger validation
          // since it's the same value. This will be better when we drop
          // 1.2 support.
          if (schema && schema.type.indexOf('array') !== -1) {
            validate(ngModel.$modelValue);
          }
 
          // We set the viewValue to trigger parsers,
          // since modelValue might be empty and validating just that
          // might change an existing error to a "required" error message.
          if (ngModel.$setDirty) {
 
            // Angular 1.3+
            ngModel.$setDirty();
            ngModel.$setViewValue(ngModel.$viewValue);
            ngModel.$commitViewValue();
 
            // In Angular 1.3 setting undefined as a viewValue does not trigger parsers
            // so we need to do a special required check. Fortunately we have $isEmpty
            if (form.required && ngModel.$isEmpty(ngModel.$modelValue)) {
              console.log('setting invalid')
              ngModel.$setValidity('tv4-302', false);
            }
 
          } else {
            // Angular 1.2
            // In angular 1.2 setting a viewValue of undefined will trigger the parser.
            // hence required works.
            ngModel.$setViewValue(ngModel.$viewValue);
          }
        };
/*
        ngModel.$formatters.push(function(val) {
          //console.log('formatters',val)
          validate(ngModel.$modelValue);
          return val
        });
*/
        // Listen to an event so we can validate the input on request
        scope.$on('schemaFormValidate', scope.validateField);
 
        scope.schemaError = function() {
          return error;
        };
      }
    };
  }]);