Skip to content

Commit 71a3053

Browse files
committed
Iron out some creases in validation
* schemaFormValidate used model value for validation, so any ordinary validation message got changed to "required". This was since we validated the model value, we can't validate the viewValue since numbers wouldn't work. So we set the viewValue again to trigger parsers. This works fine in Angular 1.2 and in 1.3 it solves the problem, but introduces another. When setting the viewValue `undefined` in 1.2 we get a nice "required", but in 1.3 parsers aren't even called. So we add an extra check with required and ngModel.$isEmpty() * In Angular 1.3 returning undefined from a parser automatically tacks on a 'parse' error. Instead we always return the viewValue and later in a special validator ('schemaForm') stop the model from getting updated. 'schemaForm' error gets filtered so it never hits the forms. In Angular 1.2 we return undefined since that doesn't tack on a 'parse' error.
1 parent 14f4aaa commit 71a3053

File tree

3 files changed

+51
-10
lines changed

3 files changed

+51
-10
lines changed

src/directives/message.js

+13-6
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,20 @@ angular.module('schemaForm').directive('sfMessage',
2121
element.html(msg);
2222
} else {
2323

24-
var errors = Object.keys(
25-
(scope.ngModel && scope.ngModel.$error) || {}
26-
);
2724

28-
// Since we use $parsers to hook up our validation we also end up with a "parse" error.
29-
// so we remove it.
30-
errors = errors.filter(function(e) { return e !== 'parse'; });
25+
var errors = [];
26+
angular.forEach(((scope.ngModel && scope.ngModel.$error) || {}), function(status, code) {
27+
if (status) {
28+
// if true then there is an error
29+
// Angular 1.3 removes properties, so we will always just have errors.
30+
// Angular 1.2 sets them to false.
31+
errors.push(code);
32+
}
33+
});
34+
35+
// In Angular 1.3 we use one $validator to stop the model value from getting updated.
36+
// this means that we always end up with a 'schemaForm' error.
37+
errors = errors.filter(function(e) { return e !== 'schemaForm'; });
3138

3239
// We only show one error.
3340
// TODO: Make that optional

src/directives/schema-validate.js

+38-3
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ angular.module('schemaForm').directive('schemaValidate', ['sfValidator', '$parse
4646
}
4747

4848
var result = sfValidator.validate(form, viewValue);
49+
50+
4951
// Since we might have different tv4 errors we must clear all
5052
// errors that start with tv4-
5153
Object.keys(ngModel.$error)
@@ -56,6 +58,15 @@ angular.module('schemaForm').directive('schemaValidate', ['sfValidator', '$parse
5658
// it is invalid, return undefined (no model update)
5759
ngModel.$setValidity('tv4-' + result.error.code, false);
5860
error = result.error;
61+
62+
// In Angular 1.3+ return the viewValue, otherwise we inadvertenly
63+
// will trigger a 'parse' error.
64+
// we will stop the model value from updating with our own $validator
65+
// later.
66+
if (ngModel.$validators) {
67+
return viewValue;
68+
}
69+
// Angular 1.2 on the other hand lacks $validators and don't add a 'parse' error.
5970
return undefined;
6071
}
6172
return viewValue;
@@ -75,7 +86,7 @@ angular.module('schemaForm').directive('schemaValidate', ['sfValidator', '$parse
7586
});
7687

7788
['$validators', '$asyncValidators'].forEach(function(attr) {
78-
// Check if our version of angular has i, i.e. 1.3+
89+
// Check if our version of angular has validators, i.e. 1.3+
7990
if (form[attr] && ngModel[attr]) {
8091
angular.forEach(form[attr], function(fn, name) {
8192
ngModel[attr][name] = fn;
@@ -84,17 +95,41 @@ angular.module('schemaForm').directive('schemaValidate', ['sfValidator', '$parse
8495
});
8596

8697
// Get in last of the parses so the parsed value has the correct type.
87-
// We don't use $validators since we like to set different errors depeding tv4 error codes
98+
// We don't use $validators since we like to set different errors depending tv4 error codes
8899
ngModel.$parsers.push(validate);
89100

101+
// But we do use one custom validator in the case of Angular 1.3 to stop the model from
102+
// updating if we've found an error.
103+
if (ngModel.$validators) {
104+
ngModel.$validators.schemaForm = function() {
105+
// Any error and we're out of here!
106+
return !Object.keys(ngModel.$error).some(function(e) { return e !== 'schemaForm'});
107+
}
108+
}
109+
90110
// Listen to an event so we can validate the input on request
91111
scope.$on('schemaFormValidate', function() {
112+
113+
// We set the viewValue to trigger parsers,
114+
// since modelValue might be empty and validating just that
115+
// might change an existing error to a "required" error message.
92116
if (ngModel.$setDirty) {
117+
93118
// Angular 1.3+
94119
ngModel.$setDirty();
95-
validate(ngModel.$modelValue);
120+
ngModel.$setViewValue(ngModel.$viewValue);
121+
ngModel.$commitViewValue();
122+
123+
// In Angular 1.3 setting undefined as a viewValue does not trigger parsers
124+
// so we need to do a special required check. Fortunately we have $isEmpty
125+
if (form.required && ngModel.$isEmpty()) {
126+
ngModel.$setValidity('tv4-302', false);
127+
}
128+
96129
} else {
97130
// Angular 1.2
131+
// In angular 1.2 setting a viewValue of undefined will trigger the parser.
132+
// hence required works.
98133
ngModel.$setViewValue(ngModel.$viewValue);
99134
}
100135

src/services/builder.js

-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ var transclusion = function() {
134134
* Builds a form from a canonical form definition
135135
*/
136136
build: function(form, decorator, slots) {
137-
console.warn(slots)
138137
return build(form, decorator, function(url) {
139138
return $templateCache.get(url) || '';
140139
}, slots);

0 commit comments

Comments
 (0)