svelte-forms-lib
svelte-forms-lib copied to clipboard
on:change and on:blur not working
-
on:change
andon:blur
are not firing with custom validation. -
on:change
is not firing with yup validation.on:blur
works with yup as expected.
So error messages do not disappear because the change or blur is not firing.
Hi @kilianso! Thanks for the issue.
-
Regarding the on:change and on:blur not firing for custom validation — that's true.. Custom validation only supports full form validation at this point. Will update to support per field validation in a future update.
-
on:change
should work with Yup validation, could you give me an example snippet on where it does not work?
Also perhaps you can try to use the on:keyup
binding:
<input on:keyup={handleChange} />
Let me know if that works for you
Here's another example on how this works — https://svelte-forms-lib-sapper-docs.now.sh/observables
Hi @tjinauyeung - thanks for your answer!
- So
keyup
is not a solution. The keyup event is not firing with custom validation anyway. Plus, even with Yup, the error message is shown as soon as the user uses tab to focus an input or starts typing, which is kinda bad UX. (e.g. when entering an email, an error is shown immediately) - Plus, there is no keyup event e.g. for a file input or a select menu (since most users are using the mouse for those field types). - Here: https://svelte-forms-lib-sapper-docs.now.sh/yup - Steps to reproduce: Enter a wrong email so the error appears. Then edit the mail so it would be valid.
on:change
is not firing and removing the error as soon as there is a valid email. You have wait for blur or submit.
So expected behaviour:
- Don't show any errors in the first place. Not on focus, not on keyup, not on change.
- On blur and on submit, show errors if a field is not valid.
- As soon as the user edits the invalid field, check "live" with on change if the field is now valid and remove the errors.
That would be perfect :)
Been wondering if actions would be a good angle to take here.
With the React informed
library one can specify a validateOnBlur
or validateOnChange
property on a field, but what may be nice here would be to allow the user to specify an event to run validation with, and to remove it from the exported handleChange
. This way handleChange
is responsible exclusively for updating the value in the store, and actions are responsible for updating the error state. e.g.:
<script>
const {handleChange, validateOn} = createForm({ /*...*/ })
</script>
<!-- specify exactly which events to run validation on -->
<input
use:validateOn={['change', 'blur']}
on:change={handleChange}
/>
If no events are specified for the validateOn
action, we could fall back to change
. This may even allow one to specify a null
event for validateOn
so that no validation is run under certain conditions, e.g.:
<script>
const {handleChange, validateOn, state} = createForm({ /*...*/ })
</script>
<!-- only validate on:change under specific conditions -->
<input
use:validateOn={[$state.myField.touched ? 'change' : null]}
on:change={handleChange}
/>
The alternative would probably be to specify the events to run validation on as an argument of the createForm
function, but I prefer the usage of actions for dynamically changing the conditions under which validations run. @larrybotha what events do you have in mind to support for validateOn
? Support for mount might be a nice addition https://formik.org/docs/api/withFormik#validateonmount-boolean
@tiaanduplessis to keep things flexible we could allow the user to pass in any DOM event and add / remove listeners dynamically:
// svelte-forms-lib/lib/actions.js
const validateAction = (node, {events} = {events: ['change']) => {
let activeEvents = [];
function addListeners(events) {
activeEvents = events;
activeEvents.map(event => node.addEventListener(event, validate);
}
function removeListeners() {
activeEvents.map(event => node.removeEventListener(event, validate);
}
addListeners(events)
return {
update(({events}) {
removeListeners();
addListeners(events);
},
destroy() {
removeListeners();
}
}
}
If an invalid event DOM event is passed, then it's no biggy - nothing happens.
validateOnMount
may be nice as a separate action to separate it from DOM events:
<input
use:validateOnMount
/>
EDIT: validateOnMount
is applicable on https://github.com/tjinauyeung/svelte-forms-lib/issues/20, but now we're getting into field vs form-level actions
I've started using https://github.com/ukchukx/svelte-inline-input and now I'm looking at ways how to use svelte-forms-lib with it as well: https://github.com/ukchukx/svelte-inline-input/issues/3
It's using on:blur
in particular to be notified of user input: https://medium.com/@ukchukx/creating-an-inline-input-component-in-svelte-and-publishing-to-npm-84274be1aa73