Code Monkey home page Code Monkey logo

svelte-forms-lib's Introduction

Svelte forms lib logo

npm version npm downloads minified size license

Svelte forms lib is a lightweight library for managing forms in Svelte, with an Formik like API.

Docs

Visit the documentation website to learn about the API and see examples.

Contributions

Please feel free to submit any issue as means of feedback or create a PR for bug fixes / wanted features.

Commit message conventions

This project uses semantic-release for versioning, which requires commit messages to adhere to a specific format.

The easiest way to write commit messages which adhere to the format is to use our npm script:

npm run commit

Join as contributor

See #30

svelte-forms-lib's People

Contributors

axtn avatar brigantian-nttdata avatar catchabus avatar dependabot[bot] avatar dhyeymoliya avatar dlebech avatar kekekevin avatar larrybotha avatar pixelmund avatar sbelzile-nexapp avatar subpx avatar tiaanduplessis avatar tjinauyeung avatar tylerrick avatar zirionneft avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

svelte-forms-lib's Issues

Helper components is missing textarea

Is your feature request related to a problem? Please describe.
There is no way to create a full-featured form with just helper components as it stands because vital components are missing.

Describe the solution you'd like
There should be more helper components like Textarea to help with full-featured form creation.

Describe alternatives you've considered
An alternative would be to do what's stated in this other issue in order to allow developers to create their own helpers. #85

Typescript defs?

Hello all,

Are there typescript defs for this project? I'd really like to use it...

Thanks

install svelte-check

Install svelte-check to provide feedback on Svelte components.

Supports both JS and TS files, so is a good first step to completing all the tasks in #97

Refactor utilities / consider alternative packages

Is your feature request related to a problem? Please describe.
Currently we are dependent on lodash.isequal which is in my opinion quite a huge module to include.
I also found out that the reach function in utils.js is never used anywhere, the reach function(getIn) uses forEach from property-expr, i don't really know why we need it.

Describe the solution you'd like
Consider much faster and smaller alternatives like dequal only a few hundred bytes.
I already tested it with dequal and all the tests pass.
If the reach function is not important i would suggest removing the function and property-expr to reduce the bundle size even more.

Describe alternatives you've considered

Additional context

Cross field validation doesn't work until the submit

Describe the bug
You can use yup.ref and you.resolve in the yup validation schema, but the validation will fail until you try to perform the submit. This issue is caused by handleChange because it validates the field with reach and without the full context.

To Reproduce
Just create a yup custom validator that uses resolve/ref or use when.

let name = this.resolve(yup.ref(nameField));

Expected behavior
You shall use the capability of use cross fields validations.

ValidateField function

We often use the binding of the form data in the input/child component:

    <input
      id="name"
      name="name"
      on:change={handleChange}
      on:blur={handleChange}
      bind:value={$form.name}
    />

The handle change play two roles:

  1. it validate the value received from the html event
  2. assign the value to the field if the value is valid

BUT: the value is already changed by the svelte binding and sometime you can't use the value from the html event because it isn't the object value, but just a string.

With a validateField function, we can solve both issues and we can trigger the field validation also when we change the value programmatically. Examples:

<script>
$form.name = "blabla"
validateField("name")
<script>

    <input
      id="name"
      name="name"
      on:change={() => validateField("name")}
      on:blur={() => validateField("name")}
      bind:value={$form.name}
    />

It could be usefull also a function that sets and validates a field

changeValue("name", value);

Add license text

Is your feature request related to a problem? Please describe.
While the documentation mentions this project is released under an MIT-style license, there is no license text provided anywhere in the codebase. As such I cannot check the license terms

Describe the solution you'd like
Provide a LICENSE.md or LICENSE.txt file

Looking for contributors!

I've created this library during a simple exploration of svelte framework, and genuinely enjoyed what I've learned about svelte. However, I'm not actively using svelte in my daily work nor have I got a side project for this. Therefore I'd like to reach out and see if anyone is interested in having a more active role in contributing to this little library and to the docs - https://svelte-forms-lib-sapper-docs.now.sh/introduction.

Give a little shout out if you are and I'll invite you to the project!

EDIT: Updated the title to reflect a more active status of the project. Super happy that a couple of devs (@larrybotha and @tiaanduplessis) joined to help out, much appreciated. For those who are also interested go ahead and add yourself in the comments or just create a PR!

Return array of all validation errors

Is your feature request related to a problem? Please describe.
$error["field"] returns 1 validation error at a time.

Describe the solution you'd like
Would like a list of all validation errors.

Describe alternatives you've considered
Passing an array of all error messages matching the field in question works.

function  validateFieldValue(field){
//Workaround
.catch((yupErrors) => {
          if (yupErrors && yupErrors.inner) {
            const vals = []
            yupErrors.inner.forEach(v => {
              v.path === field && vals.push(v.message)
            })
            return util.update(errors, field, vals)
          }
          return util.update(errors, field, error.message)})
}

Additional context
Not thoroughly tested for side-effects.

<select>'s initial default value is not synced with form store

Hi @tjinauyeung, thanks for lib.. it's pretty nice architecture
when we populate <select> elem with <option> elems on dynamically retrieved data, then browser treats first option as default selected value. but it seems form store doesn't get updates to that default value, but sits with initial filler value. only when we change to other value, it changes.

clearErrorsAndSubmit ignores validation schema

When clearErrorsAndSubmit is run it uses util.assignDeep(values, "") to "clear" the error state for the current values.

The problem I have found is with nested objects. You may have properties on an object that you dont want validated. OR in my case

country: yup .object().shape({}) .required() .nullable()

Where I do not want any properties of the country object validated. Once the form is submitted and the errors cleared, every property and all nested objects will be added to the error state object.

To Reproduce
Steps to reproduce the behaviour:

  1. As above. Validate for an object, ignoring any of its properties. error would be
    country: ""
  2. Pass validation and attempt to submit form. Once the form is cleared the error state is now something like
    country: { name:"", coords: {lat:"", lng""}}

Expected behavior
The error state should be "cleared" using the validation schema. OR could it just be set to an empty object?

Docs: add overview page

I found the high-level overview at https://formik.org/docs/guides/form-submission very helpful.

I suggest we come up with a similar page (or just copy theirs πŸ˜„) for https://svelte-forms-lib-sapper-docs.now.sh/. This would be especially helpful for folks migrating from formik, to help them quickly determine if this library works exactly the same, or in which subtle ways it behaves differently.

One question I had, for example, is whether/how svelte-forms-lib supports async submission.

Creating this page might also help reveal if we have feature parity with formik, which is something that I think would be nice to have.

Also in general, it would be nice to have more complete docs like formik and react-final-form have...

Ability to customize yup validation messages

Is your feature request related to a problem? Please describe.
When I use the library with yup validations, the error messages read like this: comment is a required field.
It would be great to be able to use the yup validation errors and customize them in a way that they are more meaningful to the user.

Describe the solution you'd like
It would be great to receive the error message that would be displayed through a callback and improve them to be more understandable.

Examples include: "Name must be at least 5 characters long", "Password needs to include a special character", etc.

Describe alternatives you've considered
I know that svelte-forms-lib also offers custom validations, but the yup variant is more concise and handles different cases automatically without the need for e.g. a regex.

How to use CheckBoxs as an input option in a form.

I'm sorry if I am missing something obvious but I am really stumped on how to create a checkbox, and I cant find anything in the documentation. I want to have the option for the user to select multiple options at a time. Just like this: https://www.w3schools.com/tags/att_input_type_checkbox.asp

, Any help would be appreciated. Thank you.

I am creating input fields using this method:
<label for="title">title</label> <select id="title" type="checkbox" name="title" on:change={handleChange} bind:value={$form.title}> <option /> <option>Mr.</option> <option>Mrs.</option> <option>Mx.</option> </select> {#if $errors.title} <small>{$errors.title}</small> {/if}

Why does isValid require all fields to be touched?

I see that isValid from createForm is not called anywhere except a test, and the requirement that all fields need to be touched to return true doesn't make a lot of sense to me.

Should the function be removed?

Add missing env vars to Travis

@tjinauyeung the build on Travis is failing: https://travis-ci.com/github/tjinauyeung/svelte-forms-lib/jobs/362498395

You'll need to add a Github token to Travis to allow Travis to push updates here:

Screenshot 2020-07-19 at 08 27 59

A GitHub personal token (https://github.com/semantic-release/github/blob/master/README.md#github-authentication) must be created and set in the GH_TOKEN or GITHUB_TOKEN environment variable on your CI environment.
Please make sure to create a GitHub personal token (https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line) and to set it in the GH_TOKEN or GITHUB_TOKEN environment variable on your CI environment. The token must allow to push to the repository tjinauyeung/svelte-forms-lib.

Provide easier API for adding/removing fields in an array

Example of nice API: react-final-form-arrays

Coming to this library from react-final-form, there are a lot of things I miss from it. I really liked how clean, consistent, and extensible it was. One of the extensions to it was react-final-form-arrays (also see this article).

This provides a really, really nice API for adding and removing new elements to/from an array of fields:

  • fields.remove(index)
  • fields.push({ firstName: '', lastName: '' }
        <FieldArray name="customers">
          {({ fields }) => (
            <div>
              {fields.map((name, index) => (
                <div key={name}>
                  <div>
                    <label>First Name</label>
                    <Field name={`${name}.firstName`} component="input" />
                  </div>
                  <div>
                    <label>Last Name</label>
                    <Field name={`${name}.lastName`} component="input" />
                  </div>
                  <button type="button" onClick={() => fields.remove(index)}>
                    Remove
                  </button>
                </div>
              ))}
              <button
                type="button"
                onClick={() => fields.push({ firstName: '', lastName: '' })}
              >
                Add
              </button>
            </div>
          )}
        </FieldArray>

Compared to current API

Compare that with the current recommended way to add/remove fields in an array, which is very verbose and boilerplatey:

    const add = () => {
      $form.users = $form.users.concat({ name: "", email: "" });
      $errors.users = $errors.users.concat({ name: "", email: "" });
    };

    const remove = i => () => {
      $form.users = $form.users.filter((u, j) => j !== i);
      $errors.users = $errors.users.filter((u, j) => j !== i);
    };

Not only is it boilerplatey, it exposes and requires knowledge of the internals of the library. And end-users of this library should not have to do all that work. And it's very easy to get one of those functions wrong. In fact, even this official example is not quite correct, because it fails to also modify $touched.users!

Bug in doc example

Here is a sandbox (based on https://svelte-forms-lib-sapper-docs.now.sh/array) showing how $touched.users should be modified too.

If you comment those 2 statements out and don't modify $touched.users when you add/remove a user, it creates a bug where if you add a new user, $isValid (initially true because it starts with 0 users) does not change from true to false. As soon as you add an empty user to the array, it should be considered invalid because name is a required field.

Related: a single store with form state instead of 3?

Ideally, I think it would be nice if we didn't have to try to keep 3+ objects ($form, $touched, $errors) in sync. Maybe there could be a centralized store of form data, keyed by field path, and under each field would be the state (value, touched, errors) for that field? I would highly recommend checking out how final-form manages state, since that is a very well-written library. (I haven't yet checked how Erik did it there but I would like to.)

Describe the solution you'd like

What I would like to see is a <FieldArray> component added to this library that works similarly to the one in
react-final-form, and provides an API that is so enjoyable, simple, and easy to use that users literally can't mess up their add/remove functions like they can with the current API.

  • fields.remove(index)
  • fields.push({ firstName: '', lastName: '' }

Form not correctly validated on submit

Describe the bug
A user may choose to update form values using the updateField method, only wanting to validate the values on submit.
From my understanding this would be the ideal process when developing accessible forms.
Currently on submit all form values are validated, but previous errors are not cleared.

To Reproduce

  • Submit form that has an error
  • Update values to fix error
  • Submit form again

Expected behaviour
The error should be cleared

Application crashes with empty initialValues object

Describe the bug
For some forms, I don't need any initialValues but then the app crashes.

To Reproduce

Works

 initialValues: {
     lastName: ''
   }

Doesn't work

 initialValues: {}

Expected behavior
It should not throw an error and crash the application.

Stacktrace

Uncaught TypeError: Cannot destructure property 'form' of 'createForm(...)' as it is undefined.
    at instance$e (Registration.svelte:9)
    at init (index.mjs:1471)
    at new Registration (Registration.svelte:185)
    at Array.create_if_block_1 (Route.svelte:31)
    at create_if_block (Route.svelte:30)
    at Object.update [as p] (Route.svelte:29)
    at update (index.mjs:765)
    at flush (index.mjs:733)
    at init (index.mjs:1501)
    at new App (App.svelte:22)

Desktop (please complete the following information):

  • OS: Ubuntu 20.10
  • Browser: Brave
  • Version 1.17.73

Validate initial data

Sometime we populate some partial data in the initialValue option, but we have to trigger the submit in order validate those fields.

It could be nice if the library will try to validate every value != null or empty.

Something like this:

    const {form, errors, isValid} = createForm({
        initialValues: {
            name: "myname", <-- VALIDATE THIS
            surname: "", <-- NO VALIDATE
            email: null, <-- NO VALIDATE
        },
        validateInitialValues: true,

how to set a variable such as validationError?

This is actually more of a question:

I have a button where I'd like to set disabled to true or false depending on wheter or not the user has checked a checkbox:

<button disabled={ !checkedTermsOfService } type="submit">Start chatting</button>

Toggling checkedTermsOfService is done like this

<input bind:checked={ checkedTermsOfService } id="termsofservice" type="checkbox" name="terms" value="accept">

Question:
I'd also like to disable the button when the another input field where the user supplies his name isn't valid

<Field name="name" id="userName" type="text"/>

I'm using Field and Form and my formProps looks like this

  const formProps = {
    initialValues:  { name: 'e.g. John Doe' },
    validationSchema: yup.object().shape({
      name: yup
        .string()
        .trim()
        .required('You left the name field empty... Please provide your temporary displayname! πŸ˜ƒ')
        .min(3, 'Your name may not be less than 3 characters long! πŸ€“')
        .max(30, 'Your name may not be more than 30 characters long! πŸ€“')
    }),
    onSubmit: values => { handleSignUpUser(values) }
  }

My button from above would now look like this (having validationError in addition to checkedTermsOfService):

<button disabled={ !checkedTermsOfService || validationError } type="submit">Start chatting</button>

Now how do I set/toggle validationError as I don't seem to have $errors available when I use the helper components such as Field and Form i.e. I don't use const { form, errors, state, handleChange, handleSubmit } = createForm({ ...}) which means I don't have the $errors observable and I can't use $errors.name in my html and or set validationError in my svelte <script> section?

Maybe there's a much simpler solution and I'm thinking to complicated based on my lack of internal knowledge of svelte-forms-lib...

<ErrorMessage/> for <Field type='checkbox'/> behaving odd

I've this html markup

                <Field name="terms" type="checkbox"/>
                <span>I agree to Foos <a href='termsofservice'>terms of service.</a></span>
                <ErrorMessage name="terms"/>

with this Yup validation object

  const formProps = {
    initialValues:  {  terms: false  },
    validationSchema: yup.object().shape({
      terms: yup.boolean().oneOf([true], 'You must agree to our terms of service!')
    }),
    onSubmit: values => {...}}

When I focus and then blur the checkbox without checking it it thows the error. That's expected. However, even if I check it after focus, then blur (i.e. leave it using TAB or the mouse), the error message doesn't disappear.

Before user interaction, all ok

image

After focus and blur, as expected, the Error message appears
image

However, even after checking the checkbox, the error message sticks around?!
image

The automated release is failing 🚨

🚨 The automated release from the master branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can resolve this πŸ’ͺ.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here is some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


No npm token specified.

An npm token must be created and set in the NPM_TOKEN environment variable on your CI environment.

Please make sure to create an npm token and to set it in the NPM_TOKEN environment variable on your CI environment. The token must allow to publish to the registry https://registry.npmjs.org/.


Good luck with your project ✨

Your semantic-release bot πŸ“¦πŸš€

<Form> does not seem to be passing slot props to parent

Describe the bug
Looking at https://github.com/tjinauyeung/svelte-forms-lib/blob/master/lib/components/Form.svelte, it appears that it's trying to / supposed to be passing the form state into the slot.

Yet when I actually try to use those slot props, they seem to be stuck at some default value, {}.

Does someone have an example demonstrating how you can actually use these slot props? Perhaps https://svelte-forms-lib-sapper-docs.now.sh/helpers could be updated to document/demo this feature?

To Reproduce

https://codesandbox.io/s/frosty-monad-heihv?file=/App.svelte demonstrates both the non-working slot props in Form and a simple demo showing slot props working in FakeForm.

The context itself is getting updated (as proven by the <ErrorMessage name="name" /> which consumes that context), but somehow the slot props are not getting updated.

What could the problem be?

Is this because context (unlike stores) are not reactive (see note at https://svelte.dev/docs#setContext)?

Hmm, but it looks like actually passes the form, errors, state, etc. stores into the slot. But if that's the case, how can you even use them? If I change errors to $errors, for example, I get this error:

Stores must be declared at the top level of the component (this may change in a future version of Svelte)

Expected behavior

I expect errors to be the same as $errors when using createForm, state the same as $state, and so on.

Project updates

A list of collaborative / project update to svelte-forms-lib which will make contributing, publishing, and fixing issues easier. Feel free to submit a PR for any of the following:

  • automate semantic version publishing to NPM
    • requires:
      • semantic-release for automatic versioning based on commit messages
      • commitizen for a commit convention that semantic-release can use to determine version numbers for releases
      • Travis / Github actions for automating publishing
  • add .prettierrc.js for consistent formatting for all contributors
    • husky pre-push hook to automate formatting for contributors not using prettier
  • add linting to tests
  • add test coverage and badge
  • add a link to a simple svelte-forms-lib codesandbox template in bug template to encourage SSCCE repros of issues
  • rewrite in TypeScript / add definitions

Dynamic Yup schema validation from JSON

Is your feature request related to a problem? Please describe.
Some forms may be dynamically created from configuration in a database, json file, etc. Given the syntax of yup, it takes some work to turn configuration into yup validation. It would be fantastic if a schema (e.g. json) could be used to dynamically generate the yup validation.

Describe the solution you'd like
From what I've found so far, a solution along the lines of this might work well as part of this module.
https://stackoverflow.com/questions/56725383/create-dynamic-yup-validation-schema-from-json

Describe alternatives you've considered
Right now I'm looking to implement the stackoverflow link separately but thought it would be a good fit as part of this module.
Edit: Just found the following: https://github.com/kristianmandrup/schema-to-yup
Edit: Found this one noted on the yup github page: https://github.com/WASD-Team/yup-ast

Value calculation

Hi and thanks for a great library! IMO this is definitely the best one atm πŸ’ͺ

Is your feature request related to a problem? Please describe.

I would like to calculate a field value that depends on another field. Say that I have blog title in one input field and in the other field I would like to generate a slug based on the title field. I also want to do this only if the slug field has not yet been touched. The reason for that is that if title field always acts as "master" a user will not be able to choose a custom slug. Hope that makes sense.

Describe the solution you'd like

Be able to pass some kind of custom input handler but I am not sure what arguments it should have because it would need access to some internal stuff deep down.

Maybe there is another, better approach that would let us use Svelte's reactivity, meaning that you setup a handler in your svelte file where you bootstrap your form, listen for changes to the $form and $touched stores somehow and act there.

As I say, I am not sure on how to solve this.

Additional context

Maybe also be able to pass a custom onInput handler to helper components directly?

Form array is no longer working

Describe the bug

Whenever you try to create a form array the error nodes aren't being created. I suspect this commit 704f461 caused this issue to happen. When I roll back to version 1.2.2 of the library it is all working as expected.

To Reproduce
Steps to reproduce the behavior:

You can see the errors here
https://codesandbox.io/s/recursing-mccarthy-wne6b?file=/App.svelte

Expected behavior

This should not error and the $errors store should have some default array values but instead, it has an empty string as its value.

erro| 'svelte/internal' does not contain an export named 'validate_slots'

Describe the bug
I have a class Name.svelte with a "@smui/textfield": "^1.0.0-beta.20", as shown below:
NB

  1. Using sapper-smui-typescript-template

  2. <script lang='typescript'> MUST be as is - no formatting spaces or error out.

<script lang='typescript'>
  import Textfield from '@smui/textfield'
  import {createForm} from 'svelte-forms-lib';
  import * as yup from 'yup'
  import HelperText from '@smui/textfield/helper-text/index';

  const {
    form, errors, state, touched, isValid, isSubmitting,
    isValidating, handleBlur, handleChange, handleSubmit
  } = createForm({
    initialValues: {
      title: '',
      name: '',
      email: ''
    },
    validationSchema: yup.object().shape({
      name: yup.string().required(),
      email: yup.string().email().required()
    }),

    onSubmit: values => {
      alert(JSON.stringify(values));
    }
  });

</script>

<form class:valid = {$isValid}
      on:submit = {handleSubmit}>

  <div>
    <Textfield id = 'email'
               name = 'email'
               type = 'email'
               label = 'Email'
               on:change = {handleChange}
               bind:value = {$form.email}/>    {#if $errors.email && $touched.email}
    <HelperText validationMsg>{$errors.email}</HelperText>    {/if}  </div>
  <div>{$errors.email}</div>
</form>

Running the app results in the following console output without the validation message being displayed, although the textfield colour changes to red and the appropriate hover message on the textfields.

node_modules/svelte-forms-lib/lib/components/Form.svelte 142:1-15
" 'svelte/internal' does not contain an export named 'validate_slots'.
node_modules/svelte-forms-lib/lib/components/Field.svelte 101:1-15
" 'svelte/internal' does not contain an export named 'validate_slots'.
node_modules/svelte-forms-lib/lib/components/Select.svelte 128:1-15
" 'svelte/internal' does not contain an export named 'validate_slots'.
node_modules/svelte-forms-lib/lib/components/ErrorMessage.svelte 142:1-15
" 'svelte/internal' does not contain an export named 'validate_slots'.
βœ” service worker (30ms)
> Listening on http://localhost:3000

To Reproduce
Copy Name.svelte and run, Listening on http://localhost:3000

Expected behavior
Error to be displayed as per docs

Screenshots
Chrome
image

Firefox
image

Desktop (please complete the following information):

  • OS: Windows 10 (most recent updates)
  • Browser [chrome, firefox] - others not checked
  • Version [chrome: Version 82.0.4082.0 (Official Build) canary (64-bit); firefox: 73.0.1 (64bit) ]

Additional context
Using sapper-smui-typescript-template

Error using rollup.js, "forEach not exported by property-expr"

Nice setup, really appreciate the fact the "helper components" are optional too.

I'm trying to plug this into a new project, I'm getting an error about property-expr not exporting forEach, is this due to my rollup config?

rollup v1.27.14
bundles src/index.ts β†’ dist/index.js...
[!] Error: 'forEach' is not exported by ../../node_modules/property-expr/index.js
https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module
../../node_modules/svelte-forms-lib/lib/util.js (1:9)
1: import { forEach } from "property-expr";

Add a way to handle/set submission errors (from backend server)

Is your feature request related to a problem? Please describe.

Some things can be / are only validated when we submit the completed form to the server. The server may respond with some validation errors of its own. We need a way to handle these errors so that the error message can be shown next to the field it applies to (if it's a field-level error) in exactly the same way as the client-side errors are displayed.

Describe the solution you'd like

I'd like to be able to return an object containing errors (that are returned from a failed submission) from my onSubmit function and have them automatically added to a submitErrors collection. This is how it works in
react-final-form (which is the awesome library I'm migrating from as I migrate to Svelte), as in this demo.

Here are some of the ways that final-form helps support submission errors (which we could consider adding to this library):

  • In the FormState object, in addition to regular (client-side) validation errors exposed as errors, it provides a submitErrors and submitError
  • Provides submitFailed which is true if the form was submitted, but the submission failed with submission errors. false otherwise.
  • Provides hasSubmitErrors: true when the form currently has submit errors. Useful for distinguishing why invalid is true.
  • invalid takes into account both errors and submitErrors:

    true if any of the fields or the form has a validation or submission error. false otherwise. Note that a form can be invalid even if the errors do not belong to any currently registered fields.

Describe alternatives you've considered

I've considered using the validate function to submit the form values to the server ... but that doesn't really work, because if the form values are valid then it won't just validate the form submission; it will also process it, which doesn't make sense to perform in the context of a validate function...

I've considered creating my own submitErrors store. And that's probably what I'll have to do as a workaround for now. Here's a sandbox showing a demo of this approach. But it's not at all integrated with the form library. So I was just hoping that we could someday get first-class support for submission errors from this library like I have enjoyed having with final-form.

on:change and on:blur not working

  1. on:change and on:blur are not firing with custom validation.
  2. 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.

Allow `<Form />` to optionally accept instance of `createForm`

Allow users to create an instance of createForm, and pass it to Form as a prop. This will ensure the user has access to all of the form methods and stores without having to bind to Form slot props.

e.g.

// Form.svelte
<script>
	// ...
	export let context = createForm(
		//...
	)

	// ...
</script>

Notes

  • onSubmit in Form would need to be assigned a default value, as use of context would make the prop redundant
    • how do we elegantly handle the conditionally required onSubmit?

Todo

  • ensure that all Form tests include user-defined context and default context variants

Related issues

  • allows for working around top-level stores not working in #56

<Field/>: select text on focus

What do you think about adding an action like this to the Field component:

export const selectTextOnFocus = ( node ) => {
  const handleFocus = event => { node && typeof node.select === 'function' && node.select() }
  node.addEventListener( 'focus', handleFocus )
  return { destroy() { node.removeEventListener( 'focus', handleFocus ) } }
}

You'd use it on an input in order to select all text on focus e.g. the inital value used with a placeholder attribute (e.g. [email protected]) and once the user clicks on the form field it would select all of [email protected] and as soon as he starts typing his own email it would delete the placeholder text and show his input without the user needing to press backspace many times to empty the input field before he can start typing.

You'd use the action from above like this:

first import it of course
import { selectTextOnFocus } from '../ui/inputActions'

then use it on an input field (the one used inside the Field component for example)
<input type='email' placeholder='[email protected]' use:selectTextOnFocus/>

More information on actions and the use directive here
https://medium.com/better-programming/practical-svelte-the-use-directive-60635671335f
https://svelte.dev/docs#use_action

Change setContext and getContext to use an actually string instead of an empty object

Is your feature request related to a problem? Please describe.
When trying to extend the library and create your own components, there is no way to get the original form properties that were created in the Form component.

Describe the solution you'd like
Changing the setContext key to be a string like "svelte-forms-lib" instead of an empty object would make this possible, this would mean that every child component of Form could get access to all information in its context.

Uncaught TypeError: Cannot read property 'validate' of undefined at HTMLSelectElement.handleChange

Describe the bug
While attempting to run the helper components demo on a fresh svelte app, the following error appears:
Uncaught TypeError: Cannot read property 'validate' of undefined at HTMLSelectElement.handleChange (createForm.js:52)

To Reproduce
Steps to reproduce the behavior:

  1. Create new svelte app (npx degit sveltejs/template svelte-app)
  2. Install svelte-forms-lib (npm i -D ....)
  3. Install yup (npm i -D yup)
  4. Edit App.svelte and copy / paste from https://svelte-forms-lib-sapper-docs.now.sh/helpers
  5. Change import yup from "yup" -> import * as yup from "yup"
  6. Add Select to the import statements.
  7. npm run dev
  8. Open app in browser and then tab through the form elements.

Expected behavior
For the fresh svelte app to work like the demo without the error.

Screenshots

Desktop (please complete the following information):

  • OS: Ubuntu 18
  • Browser: Chrome
  • Version: 80

Additional context
The Field (https://svelte-forms-lib-sapper-docs.now.sh/field) demo doesn't show the error, however it also doesn't execute the onSubmit.

Add full TypeScript support

  • add svelte-checker
  • add svelte-preprocess
  • update components to use TypeScript
    • compile Svelte components on publish to prevent users from having to compile when importing svelte-forms-lib
    • use sveld or similar to generate component definitions
  • replace .js files with typed .ts files
  • remove lib/index.d.ts
  • generate index.d.ts from .ts files
  • add tsc test to CI

<Form> passes onsubmit, etc. props on to <form> element

Describe the bug

It looks like the onsubmit, etc. props are passed on as attributes on the <form> element:

<form initialvalues="[object Object]" validate="values => true" onsubmit="values => {
      alert(JSON.stringify(values, null, 2));
}">

but they do not need to be, and this onsubmit attribute can even cause errors in apps that have a strict CSP enabled:

image

To Reproduce

Use <Form>.

https://codesandbox.io/s/vigilant-heyrovsky-4jvny?file=/App.svelte

Expected behavior

For it to only pass on the props to <form> that make sense to be passed to it (so not onsubmit).

Handle Svelte events

I have come to an issue when trying to validate custom components. I have a case where I need to be able to handle svelte events. This is because they are not fired from a HTML element and the attached value is not the same as the value of an element (example being an autocomplete where the input does not always have the same value as the value needed to be sent with the event)

It would be great to be able to pass a Svelte event to the handleChange method. This would give more flexibility when handling these events.

Probably something like dispatch('eventName', {name,value});

I am happy to contribute, just wondering what your thoughts are?

Thanks for good work on the lib.

Conserve previous values when using updateInitialValues

Is your feature request related to a problem? Please describe.
Currently, updateInitialValues only reassigns whatever you pass it into a new object. All previous values are lost.

In my opinion, most of the time updateInitialValues is used to get updated values from an API endpoint, where you might only want to change a subset of the initialValues, similar to a PATCH request.

Describe the solution you'd like
Change the behavior of updateInitialValues to spread new values in and combine those with the same key naming.
This would be more the behavior that at least I expect from it.

Describe alternatives you've considered
An alternative would be to spread the previous values myself, but this requires to have them available easily and sometimes means passing parameters across multiple methods potentially.

Additionally, there is no documentation for updateInitialValues on the website, it would be great to have it!

Get values when using multiple submit buttons

Is there a way to get the value of which submit button was pressed when we have several ones?
From what I've tried it looks like there isn't, but I thought I would ask just in case.

TextArea, CheckBox

Is your feature request related to a problem? Please describe.
Feature request: Expose "key" in key.js.

Thanks! I've used Formik in the past and your implementation is very easy to understand.
I needed to use textarea and checkboxes (modifying value to true/false), but the slots in Form don't give me access to the "key" to the store. So, I couldn't add custom components.

Describe the solution you'd like
Allowing let:key would open up to custom components. Of course, could add the most common ones to the library, but just exposing the key in key.js would suffice -- I think.

Describe alternatives you've considered
I copied the library into my source to make these customizations, which is not optimal.

Make validate function optional; Cannot read property 'then' of undefined at updateValidateField

Describe the bug

Even with the basic example at https://svelte-forms-lib-sapper-docs.now.sh/basic, I'm getting this error:

image

  function updateValidateField(field, value) {
    return validateFieldValue(field, value).then(function () {
      updateField(field, value);
    });
  }

To Reproduce

Use the example from https://svelte-forms-lib-sapper-docs.now.sh/basic

Expected behavior

No errors

Desktop (please complete the following information):

  • OS: Ubuntu
  • Browser Chrome, Firefox

Documentation is a bit incorrect

Describe the bug
When using examples with yup - breaks with Error: 'default' is not exported by ...
To Reproduce
Steps to reproduce the behavior:
Just copypase the example from docs page
Expected behavior
Should probably use import * as yup from 'yup'; instead of import yup from 'yup'

formProps dynamic initialValues are no changing

Hello! I am not sure if this is a bug but is something that is working wrong for me.

I am making a CRUD for a entity called Material where on update, a Modal-Form should show the data of "related material". For that I create a store for the currentMaterial which is the "related material", and a derived store for the formProps that use currentMaterial as initialValues and that working fine. The problem occur on the <Form {...$formProps}> statement that appears that Form's initialValues are not changing even when the $formProps have changed.

Screenshots
Here is an example of what the form values are and what the $formProps initialValues actually are.
image

Here is my code:
store
material

Nope validator

Would it be thinkable to implement Nope validation as it's similar to Yup but claims to be considerably smaller and faster?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.