Open repolevedavaj opened 8 years ago
Sounds like a validation error? Ie, your decorator is creating a date input field that is throwing a date as a string on the model, but validation is expecting an actual js Date object on the model? Make sure whatever date input being generated for that schema object is setup to add a date object on the model. Generally date inputs will be of type string with format of datetime or something along those lines. This will allow validation to not throw that error when the string of the date gets applied to the model.
The reason why i do not want to use input of type string
is because it would not support the mobile browser specific implementation of date picker. But I think I found the reason why it is throwing a validation error. While validating, the function validateType(...)
in the tv4.js
is called, where the type of the validated data is determined. In my case the validated data is a js Date
object, but is considered as of type object
.
So to solve my issue, it changed some small things:
{
type: "object",
properties: {
birthday: {
type: "object", // object so it matches the type determined in tv4.js
format: "date"
}
}
}
angular.module('schemaForm').config(['schemaFormProvider', 'schemaFormDecoratorsProvider', 'sfPathProvider',
function (schemaFormProvider, schemaFormDecoratorsProvider, sfPathProvider) {
var datepicker = function (name, schema, options) {
if (schema.type === 'object' && schema.format === "date") {
var f = schemaFormProvider.stdFormObj(name, schema, options);
f.key = options.path;
f.type = 'date';
options.lookup[sfPathProvider.stringify(options.path)] = f;
return f;
}
};
schemaFormProvider.defaults.object = [];
schemaFormProvider.defaults.object.unshift(datepicker);
}
]);
Now the date from the input field is successfully saved in the model. I do not know if it is the final solution that I will use, but is is working for now.
How I fixed it was: Add this conditional to the /angular-schema-form/src/services/validator.js around line 39
// Date values
if ( schema.type === 'string' && schema.format === 'date' ) {
if ( value === null ) {
value = undefined;
} else {
if ( typeof value.toISOString === 'function' ) {
value = value.toISOString();
}
}
}
@brianpkelley This fixes the issue, but introduces an issue with the validation. After you clear the field the validation sticks saying it's successful.
I was able to resolve the validation remaining green by adding this:
if (schema.type === 'string' && schema.format === 'date' && viewValue === null && !form.required) {
ngModel.setPristine();
return undefined;
}
to line 2769 in the angular-schema-form/dist/schema-form.js of the release from the master branch.
Line 2769 starts with the following code for checking if the result is valid:
if (!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.
if (ngModel.$validators) {
return viewValue;
}
// Angular 1.2 on the other hand lacks $validators and don't add a 'parse' error.
return undefined;
}
return viewValue;
};
https://github.com/json-schema-form/angular-schema-form-material/issues/18#issuecomment-239635625 I don't recall the exact circumstances that led me to the solution I posted on the link above, but it may offer more help if needed.
@brianpkelley I'm having a hard time thinking it's best to solve this issue by adding a tv4 format and not adding a solution directly into ASF. It seems @Anthropic really favors your choice. But it seems like creating a decorator to resolve an issue isn't the right path, for something that is provided by default.
However, because I am using a decorator for my date fields ANYWAYS, I have chosen to implement your changes. While this does properly validate the date, with the exception of the validation message not applying the correct message as stated by @brianpkelley's solution in the other thread ema-form/angular-schema-form-material#18 (comment). It is expecting a valid of type object even if the field is not required and shows the field as invalid.
Here is my implementation:
// ISO Format - 2016-08-02T17:03:18.608Z - new Date().toISOString()
var dateFormat = /^[0-9]{4,}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\.[0-9]+|)(?:[+-][0-9]{2}:?(?:[0-9]{2}|)|Z)$/;
// Standard Format - Tue Aug 02 2016 12:03:59 GMT-0500 (CDT) - new Date().toString()
var mdDateFormat = /^(:?[A-Z][a-z]{2}\s){2}\d{1,2}\s\d{4}\s(:?\d{2}\:?){3}\s[A-Z]{3}\-\d{4}\s\([A-Z]{3}\)$/;
var formats = {
date: function (value) {
if ( value && typeof value !== 'string' && value.toISOString ) {
value = value.toISOString() || '';
}
if (dateFormat.test(value) ) {//|| !mdDateFormat.test(value)
return null;
}
return 'A valid date expected';
}
};
tv4.addFormat( 'date', formats.date );
function dateObjectDefault(name, schema, options) {
if (schema.type === 'object' && (schema.format === 'date' || schema.format === 'date-time')) {
var f = schemaFormProvider.stdFormObj(name, schema, options);
f.key = options.path;
f.type = 'date';
options.lookup[sfPathProvider.stringify(options.path)] = f;
return f;
}
};
schemaFormProvider.defaults.object.unshift(dateObjectDefault);
Above, I used @brianpkelley's solution.
While adding my solution to line 2890 of Angular-schema-form.js Or rather line 41 of src/directives/schema-validate.directive.js
if ((schema.type === 'object' || schema.type === 'string') && schema.format === 'date' && viewValue === null && !form.required) {
//ngModel.$setValidity('tv4-', null);
ngModel.$setPristine();
return undefined;
}
This only solves one of the many notable issues, you can see while playing around with validation on a date field. For instance, you can even have a date required, and not provide a value and still have it validate successfully.
@krptodr I would love to come up with a solution to this that works for everyone, dates are a pain, I assume that's why Textalk made the original datepicker add-on for the library as a separate item. I would like to add a stable datepicker to the bootstrap repo and whatever changes are required here, ideally if there was a main datepicker as part of bootstrap (I don't use bootstrap much so I have never checked) it would be the preferred choice and any behaviour here would have to cater for that. It just isn't high on my TODO list so it wouldn't be for a while unless someone wants to make a PR with one.
Since json schema draft 4 does not support custom types AND has a built in string date-time format (ISO8601), maybe the best way to tackle this is to force conversion of date objects to strings prior to validation.
So, if a jsonSchema is defined as this:
"mydate": {
"id": "/properties/mydate",
"type": "string",
"format": "date-time"
}
angular-schema-form could coerce the date object into a string, somewhere prior to calling tv4 validation:
if (value instanceof Date) {
value = value.toISOString();
}
First: Thanks for this really cool and easy to use framework!
I would like to use a input field of type 'date' to support browser specific date picker implementations, but it always shows the error 'Invalid type, expected date' and i do not know where this comes from. If I insert an date input field manually and bind it with
ng-model
to a date object, it seems no problem.I use the following schema
form
and configure the
schemaFormProvider
like this:Could you tell me where I am going wrong?