Custom tv4 keyword ignored by $broadcast('schemaFormValidate')
I've a custom tv4 keyword defined like this
tv4.defineKeyword('email', function(data, value, schema) {
if (schema.email) {
if (/^\S+@\S+$/.test(data)) {
return null;
}
return {code: 10001};
}
return null;
});
and a custom error like this
tv4.defineError('EMAIL', 10001, 'Invalid email address');
and I'm configuring sfErrorMessageProvider like this on startup
app.config(['sfErrorMessageProvider', function(sfErrorMessageProvider) {
sfErrorMessageProvider.setDefaultMessage(10001, 'Invalid email address');
}]);
In my schema I have the following definition
"CONTACTEMAIL": {
"type": "string",
"maxLength": 255,
"email": true
}
My field definition is like this
{
"key": "CONTACTEMAIL",
"placeholder": "Enter contact email",
"feedback": false
}
Before submitting my form I call $scope.$broadcast('schemaFormValidate'), however the field is not validated. For example when it contains the data "NULL" (as a string). This happens when I open an edit form and supply the form data, the model value directly. The field will be initialised with the value "NULL".
However, if I edit the field manually everything works just fine. The field is marked as invalid, my error message shows up.
Right now, as a workaround I'm marking my form with sf-options="{validateOnRender: true}". This way the following happens:
- the field initially won't be marked as erroneous (at least not with the related CSS classes, so the field is not red)
- when I call
$broadcast('schemaFormValidate')it will be marked as erroneous (it'll be red) - however, the validation message won't show up until I type something in the field
So, validateOnRender: true isn't completely ideal, but this at least prevents invalid form submission.
Any idea?
I've created an example plunk here. However ... in this simple plunk it seems to work. I reckon that the same stuff isn't working for me, because in my actual application I'm showing my form in a modal window (angular-strap modal) and in this case there is some magic involved with scopes, naming and stuff. Here's a link that describes it. I'll get back with some more info this either to update or to close the issue.
I've updated my plunk, but it still seems to work. Something is different on my end. Will try and sort it out. Closing the issue.
Okay, figured it out. The schema form version in the plunker is different than the one I'm using. I was not able to create a plunk while linking every dependency from external sites so I've just based my plunks on available ones.
See this plunker where I've updated schema forms to 0.8.12.
I've used these files' contents to replace schema-form.js and bootstrap-decorator.js.
The latest version that still works is 0.8.2. The next one, 0.8.3 seems to be having the same issue.
@kohanyirobert could you do me a huge favour and try with the recent 0.8.13 code? There were some PRs in that related to re-broadcasting validations, possibly not related, but I would really apprciate your help to confirm it isn't fixed.
ps. thanks so much for the plunkers, if only every issue could be reported with so much detail!
Sadly version 0.8.13 does not fix this. :(
@kohanyirobert thank you for that!
@kohanyirobert @Anthropic Is there any temporary solution ?
@thiagog3 I'm still using version 0.8.2 and that works, haven't tried newer versions. I'm content with this.
For another project I'm using this instead: https://github.com/jdorn/json-editor/, there is an Angular binding to it (which is a bit dodgy, but it works: https://github.com/rodikh/angular-json-editor). Not perfect either, but it can handle generating forms from complex schemas better (I have a reaaaaally complex form and it can handle it, validation and all, but the schema needs to be quite on-point for it work).
@kohanyirobert the issue is actually a feature of ngModel, when you type in the text field if the value is invalid ngModel removes it from the model, so then when validating the entire form it no longer applies as the model it sends to the custom validator no longer contains the item to test against.
Thankfully there's an easy way around this is using ng-model-options="{ allowInvalid: true }" which will produce the result you are after.
@thiagog3 fyi ^