-
Notifications
You must be signed in to change notification settings - Fork 533
Introduce a new state for validation class. #257
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce a new state for validation class. #257
Conversation
src/formGenerator.vue
Outdated
@@ -342,6 +357,11 @@ div.vue-form-generator(v-if='schema != null') | |||
return res.map(item => item.error); | |||
}, | |||
|
|||
fieldTouched(field) { | |||
let res = this.touched.filter(e => e.field == field); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could use
let field = this.touched.find(e=>e.field == field)
which returns null or the first match. This way you don't have to use res.map(item => item.touched)[0];
which is not very safe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes sorry, I was tired when I did that and did not bother to write good code. Thank you !
@@ -283,6 +286,12 @@ div.vue-form-generator(v-if='schema != null') | |||
onFieldValidated(res, errors, field) { | |||
// Remove old errors for this field | |||
this.errors = this.errors.filter(e => e.field != field.schema); | |||
this.touched = this.touched.filter(e => e.field != field.schema); | |||
|
|||
this.touched.push({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why push touched fields every time a validation occurs?
Maybe have a logic
if( findTouchedField(field) == null)
this.touched.push...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because it is cleaned at every validation
|
||
this.$children.forEach((child) => { | ||
if (isFunction(child.validate)) | ||
{ | ||
this.touched.push({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering if it's not easier to have touched
inside field data
, initialize it with false and when you call this validation method you simply push to this array that value. This should happen only upon first validation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact, I started with this strategy (to have touched inside field data), but I didn't think about doing what you suggest.
The problem is that the style is decided getFieldRowClasses
(in formGenerator.vue
). This method argument is the field definition from the schema. This field definition is what is used to match "local" errors with "global" errors (fieldErrors
for example).
I don't know why @icebob used this way to match things, but I can assume that there is a reason for it, a consequence I don't foresee right now (maybe for groups ?).
Anyway, I'm going to try another way to match fields for touched
property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well the idea would be that you still have this touched
array only that the touched property is kept inside the field just like errors https://github.com/icebob/vue-form-generator/blob/master/src/fields/abstractField.js#L27
You would keep touched
inside abstractField data and change upon validation of the field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I understand, as I said, this was my first idea. But how do you access touched
from formGenerator
?
I was going to add an index to the v-for loop ((field, index) in fields
), but I noticed that groups will break this (I just noticed groups are not working how I assumed they would and this is another problem).
Anyway, changing an internal touched
property is not the problem, accessing it from the parent (formGenerator
) is the difficulty. How to match the children with the parent ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just like it's done with errors. Iterate over children
Another, more cleaner way IMHO would be to have something like this:
Child field:
mounted(){
this.$parent.addField(this)
},
destroyed() {
if (this.$el && this.$el.parentNode) {
this.$el.parentNode.removeChild(this.$el);
}
this.$parent.removeField(this);
},
Parent
addField(item) {
const index = this.$slots.default.indexOf(item.$vnode);
this.fieldData.splice(index, 0, item);
},
removeField(item) {
const index = this.fieldData.indexOf(item);
if (index > -1) {
this.fieldData.splice(index, 1);
}
}
And you have all child info inside fieldData
(including errors, touched property etc)
But that is probably out of scope now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a special data type/class which represents a component or a tree of elements in vue
https://github.com/vuejs/vue/blob/dev/src/core/vdom/vnode.js
It basically contains the element, tag, component data and many other things. Since slots return a list of $vnodes
then you can do the extra check and see if the component you are trying to add exists in slots if slots are used. Since vfg uses component :is
, then the filtering probably can be done based on $children
maybe
Anyway that was an idea/draft which I copy pasted from one of my components so it has to be adapted to vfg implementation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel so dumb right now 😅
I didn't now about this at all... My understanding of Vue is far from complete.
I like your solution a lot. Maybe I can introduce it only for this new state for now, and maybe move errors and other functionalities later if no problem arise ?
If I understand correctly, I need to change that:
addField(item) {
const index = this.$slots.default.indexOf(item.$vnode);
this.fieldData.splice(index, 0, item);
}
into this:
addField(item) {
const index = this.$children.default.indexOf(item.$vnode);
this.fieldData.splice(index, 0, item);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addField(item) {
const index = this.$children.findIndex(field=> field.$vnode == item.$vnode);
this.fieldData.splice(index, 0, item);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok so your solution doesn't work.
When validateAfterLoad
is true, the loop will trigger getFieldRowClasses
before any field component initialization (created
or mounted
) and thus fieldData
is empty, causing an error.
I think a solution like this would need a big rewrite of VFG internal.
I'm sorry but I cannot allow myself to lose any more time on this. I'm going to implement the fixes you suggested but I will keep this "dirty" for now.
Hope you understand, thank you for your help and feel free to do another PR with a better solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure no problem. Those were only suggestions, If they take too much time then any solution is ok
@lionel-bijaoui Are you going to fix the errors? And make tests to cover the new property? |
Sorry I missed your approval. I'm working on that tomorrow. |
Is this still being worked on? I can imagine this is a pretty nice feature to have; a lot of forms require success styling to be triggered when a user has really touched the field. |
I'm going to rework on this for the v3, closing this PR |
#253
This is copying the way errors works.
While it work, I'm sure their is a better way to do validation.
I don't know yet how to change the test to pass, but since this may change I'm not going to change it for now.
Thank you for any feedback !