Open donalmurtagh opened 7 years ago
I would suggest not using $validators from the ui-schema, instead if you have a controller or a directive to manage it, then you can make scope available to it when you define it.
I would suggest not using $validators from the ui-schema
Based on the example above, it isn't possible to do this with $validators
, because the validation function only provides access to the value of the field itself, or am I missing something?
instead if you have a controller or a directive to manage it, then you can make scope available to it when you define it.
Are you suggesting that I should implement this with an addon?
One solution I'd considered is to define an addon which validates the field by calling back into a function defined in the form/schema with this signature
function (fieldValue, model) { }
In the case of my example above, the function would be defined like so:
function (fieldValue, model) {
if (model.gender === 'MALE') {
return angular.isString(fieldValue) && fieldValue.indexOf('Bob')
}
return true;
}
@donalmurtagh if you look at setting up defaults you can see the use of the provider to apply form attribute selection, you could apply your validator to f as the f value in the example is the form definition and I would expect that adding the validator here where it can access your scope would work and can be done within your controller or an add on.
Disclaimer: I have not tried it so cannot guarantee it works.
Im also having trouble here. I need to make sure several values are not the same but I have no access to the model in my validator.
@Anthropic, your suggestion above seems it would affect every instance of that type of field. That doesn't seem viable, or the right way to do things. Even if we managed a way to turn that specific validator on or off we still have the issue of integrating with schema form / tv4. How do we set validity of the field? How do we set validation messages? It seems like a lot of work creating bespoke directives for every validation scenario when all we need is a second argument with a copy of the model (and probably the form at the level the change was made so we can tell where it was in our form we made that change)
@donalmurtagh @Lorless the issue is $validator is not an ASF feature and it is passed directly to Angular as is, Angular is the one that only passes a single model value to the function.
I suspect you could try using a wrapper around the code that adds the validator, change
[ '$validators', '$asyncValidators' ].forEach(function(attr) {
// Check if our version of angular has validators, i.e. 1.3+
if (form[attr] && ngModel[attr]) {
angular.forEach(form[attr], function(fn, name) {
ngModel[attr][name] = fn;
});
}
});
Into this
[ '$validators', '$asyncValidators' ].forEach(function(attr) {
// Check if our version of angular has validators, i.e. 1.3+
if (form[attr] && ngModel[attr]) {
angular.forEach(form[attr], function(fn, name) {
ngModel[attr][name] = function(modelValue, viewValue) {
return fn(modelValue, viewValue, scope.model, form);
};
});
}
});
If one of you want to try that and see if you could get it working I'd love confirmation it works or a PR or even just details on modifications to get it working :)
Didn't mean to close, if someone can confirm the solution I suggested either works or offer suggested changes it would be a great help toward the issue :)
@Anthropic Ill test this out tonight :)
@donalmurtagh @Lorless any feedback?
@Anthropic not yet, but it's still very much on my radar. I expect to get to this within the next week or two. Sorry for the delay.
You can access other field values in the validator function (third parameter):
(tested on Angular 1.6)
$validators: {
foo: function(newValue, oldValue, form) {
if (form.bar === 'Male') {
// do domething because it's male (that's sexist)
}
}
}
@tivie thanks, that's very useful to know. This should be added to the docs
The docs include this example that shows how to write a custom validator for a field:
Is it somehow possible to use other field values in a custom validator? For example, if we want to apply the validation above only if
model.gender == 'MALE'
?