svelte-forms-lib icon indicating copy to clipboard operation
svelte-forms-lib copied to clipboard

Update `$touched` and `$errors` stores when form value is bound only with `bind:value={$form.someValue}`

Open larrybotha opened this issue 3 years ago • 3 comments

PRs are welcome!

Problem to solve

As a developer, when I don't use the handleChange helper, I want the other stores to be updated when a form value is updated, so I can simplify my form implementations.

Intended users

  • developer

User experience goal

The user should be able to use an input with svelte-forms-lib with the bind:value={$form.somValue} syntax without relying on handleChange to keep the other stores updated.

Proposal

  • add a subscribe handler to form in createForm that:
    • handles changes to form values
    • updates all other stores accordingly when a form value changes. i.e. $errors, $touched, $modified, etc.
  • add tests for each type of store
    • [ ] test $errors is updated
    • [ ] test $modiifed is updated
    • [ ] test $touched is updated
  • refactor handleChange so that it either forwards to form.subscribe, or uses the same handler as form.subscribe

Further details

  • a demo of the issue can be seen here: https://codesandbox.io/s/competent-jackson-i12rq?file=/App.svelte
    • the form values are bound only with bind:value={$form...email}
    • when a form value changes, the $touched store is not updated, as the $touched store relies on handleChange for its values to be updated.

Links and references

  • A discussion with a proposal for form.subscribe can be found in #105

larrybotha avatar Mar 18 '21 08:03 larrybotha

@larrybotha Thanks a lot to put it clearly in this new issue !

rccc avatar Mar 18 '21 11:03 rccc

I think I just encountered this issue right now. I use updateInitialValues to update selected values from svelte-select, so the form values are updated, but the $errors validation is wrong. Is there any workaround for it?

mcmxcdev avatar Nov 03 '21 09:11 mcmxcdev

I took a few hours but I manage to have a workaround that works in all my rare cases where I was not using inputs or similar but I still wanted to handleChanges. What I do is to import validateField from createForm and call it manually when I trigger a specific change on a field I am tracking.

For instance:

// Notice bind:checked is not correct, it is coming from a material Switch Component, this is only an example
<Button role="switch" aria-checked={$form.terms} bind:checked={$form.terms} on:click={() => validateField('terms')}>
{checked ? 'Accepted' : 'Not accepted'}
</Button>

I left an example of this with the sandbox provided above, you can notice $errors $touched and $form are getting updated accordingly without calling handleChange and relying on DOM props.

https://codesandbox.io/s/stoic-thompson-crg75?file=/App.svelte:1290-1395

Egnus avatar Nov 22 '21 17:11 Egnus