Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/nathancahill/sveltik
Powerful forms in Svelte, inspired by Formik.
https://github.com/nathancahill/sveltik
forms svelte
Last synced: 2 days ago
JSON representation
Powerful forms in Svelte, inspired by Formik.
- Host: GitHub
- URL: https://github.com/nathancahill/sveltik
- Owner: nathancahill
- License: mit
- Created: 2020-02-11T10:11:15.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2023-01-05T16:24:31.000Z (almost 2 years ago)
- Last Synced: 2024-12-22T11:36:34.670Z (4 days ago)
- Topics: forms, svelte
- Language: JavaScript
- Homepage:
- Size: 2.1 MB
- Stars: 194
- Watchers: 9
- Forks: 8
- Open Issues: 11
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Sveltik ![CI](https://github.com/nathancahill/sveltik/workflows/CI/badge.svg)
Forms in Svelte, inspired by [Formik](https://jaredpalmer.com/formik/).
```html
import { Sveltik, Form, Field, ErrorMessage } from 'sveltik'
let initialValues = {
email: '',
password: '',
}let validate = values => {
const errors = {}
if (!values.email) {
errors.email = 'Required'
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)) {
errors.email = 'Invalid email address'
}
return errors
}let onSubmit = (values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2))
setSubmitting(false)
}, 400)
}
Submit
```
## ``
`` is a component for rendering forms. It is largely a port of
[Formik](https://jaredpalmer.com/formik/docs/api/formik) to Svelte and broadly
follows the same API. It uses a `let:props` pattern which is generally similar to
the render prop pattern in React.### Example
[Open in REPL](https://svelte.dev/repl/5ba56f98dc7f4911818ec5617c6b3024?version=3)
```html
import { Sveltik } from 'sveltik'
My Form
{
setTimeout(() => {
alert(JSON.stringify(values, null, 2))
actions.setSubmitting(false)
}, 1000)
}}
let:props
>
{#if props.errors.name}
{props.errors.name}
{/if}
Submit
```### Props
- `enableReinitialize?: boolean`
- `initialErrors?: SveltikErrors`
- `initialStatus?: any`
- `initialTouched?: SveltikTouched`
- `initialValues: Values`
- `initialWarnings?: SveltikWarnings`
- `onReset?: (values: Values, sveltikBag: SveltikBag) => void`
- `onSubmit: (values: Values, sveltikBag: SveltikBag) => void | Promise`
- `validate?: (values: Values, sveltikBag: SveltikBag) => SveltikErrors`
- `validateOnBlur?: boolean`
- `validateOnChange?: boolean`
- `validateOnMount?: boolean`### let:props
- `let:props: SveltikProps`
- `let:isDirty: boolean`
- `let:errors: { [field: string]: string }`
- `let:handleBlur: (e: HTMLBlurEvent) => void`
- `let:handleInput: (e: HTMLInputEvent) => void`
- `let:handleReset: () => void`
- `let:handleSubmit: (e: HTMLFormEvent) => void`
- `let:isSubmitting: boolean`
- `let:isValid: boolean`
- `let:isValidating: boolean`
- `let:resetForm: (nextInitialState?: SveltikState) => void`
- `let:scrollFirstErrorIntoView: () => void`
- `let:setErrors: (fields: { [field: string]: string }) => void`
- `let:setFieldError: (field: string, errorMsg: string) => void`
- `let:setFieldTouched: (field: string, isTouched?: boolean, shouldValidate?: boolean) => void`
- `let:setFieldValue: (field: string, value: any, shouldValidate?: boolean) => void`
- `let:setFieldWarning: (field: string, warning: string) => void`
- `let:setStatus: (status?: any) => void`
- `let:setSubmitting: (isSubmitting: boolean) => void`
- `let:setTouched: (fields: { [field: string]: boolean }, shouldValidate?: boolean) => void`
- `let:setValues: (fields: { [field: string]: any }, shouldValidate?: boolean) => void`
- `let:setWarnings: (fields: { [field: string]: string }) => void`
- `let:status: any`
- `let:submitAttemptCount: number`
- `let:submitFailure: () => void`
- `let:submitFailureCount: number`
- `let:submitForm: () => Promise`
- `let:submitSuccess: () => void`
- `let:submitSuccessCount: number`
- `let:touched: { [field: string]: boolean }`
- `let:values: { [field: string]: any }`
- `let:validateForm: (values?: any) => void`
- `let:validateField: (field: string) => void`
- `let:warnings: { [field: string]: string }`### Reference
#### Props
##### `enableReinitialize?: boolean`
Default is false. Control whether Sveltik should reset the form if `initialValues` changes (using deep equality).
##### `initialErrors?: SveltikErrors`
Initial field errors of the form, Sveltik will make these values available to render methods component as `errors`.
##### `initialStatus?: any`
An arbitrary value for the initial `status` of the form. If the form is reset, this value will be restored.
##### `initialTouched?: SveltikTouched`
Initial visitied fields of the form, Sveltik will make these values available to render methods component as `touched`.
##### `initialValues: Values`
Initial field values of the form, Sveltik will make these values available to render methods component as `values`.
Even if your form is empty by default, you must initialize all fields with initial values.
##### `onReset?: (values: Values, sveltikBag: SveltikBag) => void`
Your optional form reset handler. It is passed your forms `values` and the "SveltikBag".
##### `onSubmit: (values: Values, sveltikBag: SveltikBag) => void | Promise`
Your form submission handler. It is passed your forms `values` and the "SveltikBag", which includes an object containing a subset of the injected props and methods (i.e. all the methods with names that start with `set` + `resetForm`) and any props that were passed to the wrapped component.
If `onSubmit` returns a promise, rejection automatically calls `submitFailure` and resolution automatically calls `submitSuccess`.##### `validate?: (values: Values) => SveltikErrors`
Validate the form's `values` with function. Synchronous and return an `errors` object.
##### `validateOnBlur?: boolean`
Default is `true`. Use this option to run validations on `blur` events. More specifically, when either `handleBlur`, `setFieldTouched`, or `setTouched` are called.
##### `validateOnChange?: boolean`
Default is `true`. Use this option to tell Sveltik to run validations on `change` events and `change`-related methods. More specifically, when either `handleInput`, `setFieldValue`, or `setValues` are called.
##### `validateOnMount?: boolean`
Default is `false`. Use this option to tell Sveltik to run validations when the `` component mounts and/or `initialValues` change.
#### let:props
All of these props are exposed individually as well as a master `let:props` prop which is an object
of all available props.##### `let:isDirty: boolean`
Returns `true` if values are not deeply equal from initial values, `false` otherwise. `dirty` is a readonly computed property and should not be mutated directly.
##### `let:errors: { [field: string]: string }`
Form validation errors. Should match the shape of your form's values defined in `initialValues`.
##### `let:handleBlur: (e: HTMLBlurEvent) => void`
`onBlur` event handler. Useful for when you need to track whether an input has been `touched` or not. This should be passed to
``##### `let:handleInput: (e: HTMLInputEvent) => void`
General input change event handler. This will update the `values[key]` where `key` is the event-emitting input's `name` attribute. If the `name` attribute is not present, `handleInput` will look for an input's `id` attribute. Note: "input" here means all HTML inputs.
##### `let:handleReset: () => void`
Reset handler. Will reset the form to its initial state. This should be passed to `...`
##### `let:handleSubmit: (e: HTMLFormEvent) => void`
Submit handler. This should be passed to `...`.
##### `let:isSubmitting: boolean`
Submitting state of the form. Returns `true` if submission is in progress and `false` otherwise.
##### `let:isValid: boolean`
Returns `true` if there are no `errors` (i.e. the `errors` object is empty) and `false` otherwise.
##### `let:isValidating: boolean`
Returns `true` if Sveltik is running validation during submission, or by calling `validateForm` directly false otherwise.
##### `let:resetForm: (nextInitialState?: SveltikState) => void`
Imperatively reset the form. If `nextInitialState` is specified, Sveltik will set this state as the new "initial state" and use the related values of `nextInitialState` to update the form's `initialValues` as well as `initialTouched`, `initialStatus`, `initialErrors`. This is useful for altering the initial state (i.e. "base") of the form after changes have been made. If `nextInitialState` is not defined, then Sveltik will reset state to the original initial state.
##### `let:scrollFirstErrorIntoView: () => void`
Scroll the first `` with an error into view. First is calculated by the vertical distance from the top of the document.
##### `let:setErrors: (fields: { [field: string]: string }) => void`
Set `errors` imperatively.
##### `let:setFieldError: (field: string, errorMsg: string) => void`
Set the error message of a field imperatively. `field` should match the key of `errors` you wish to update. Useful for creating custom input error handlers.
##### `let:setFieldTouched: (field: string, isTouched?: boolean, shouldValidate?: boolean) => void`
Set the touched state of a field imperatively. `field` should match the key of `touched` you wish to update. Useful for creating custom input blur handlers. Calling this method will trigger validation to run if `validateOnBlur` is set to `true` (which it is by default). `isTouched` defaults to `true` if not specified. You can also explicitly prevent/skip validation by passing a third argument as `false`.
##### `let:setFieldValue: (field: string, value: any, shouldValidate?: boolean) => void`
Set the value of a `field` imperatively. `field` should match the key of `values` you wish to update. Useful for creating custom input change handlers. Calling this will trigger validation to run if `validateOnChange` is set to `true` (which it is by default). You can also explicitly prevent/skip validation by passing a third argument as `false`.
##### `let:setFieldWarning: (field: string, warning: string) => void`
Set the warning of a `field` imperatively. `field` should match the key of `warnings` you wish to update.
##### `let:setStatus: (status?: any) => void`
Set a top-level `status` to anything you want imperatively. Useful for controlling arbitrary top-level state related to your form. For example, you can use it to pass API responses back into your component in `handleSubmit`.
##### `let:setSubmitting: (isSubmitting: boolean) => void`
Set `isSubmitting` imperatively. You would call it with `setSubmitting(false)` in your `onSubmit` handler to finish the cycle.
##### `let:setTouched: (fields: { [field: string]: boolean }, shouldValidate?: boolean) => void`
Set `touched` imperatively. Calling this will trigger validation to run if `validateOnBlur` is set to `true` (which it is by default). You can also explicitly prevent/skip validation by passing a second argument as `false`.
##### `let:setValues: (fields: { [field: string]: any }, shouldValidate?: boolean) => void`
Set `values` imperatively. Calling this will trigger validation to run if `validateOnChange` is set to `true` (which it is by default). You can also explicitly prevent/skip validation by passing a second argument as `false`.
##### `let:setWarnings: (fields: { [field: string]: string }) => void`
Set `warnings` imperatively.
##### `let:status: any`
A top-level status object that you can use to represent form state that can't otherwise be expressed/stored with other methods. This is useful for capturing and passing through API responses to your inner component. `status` should only be modified by calling `setStatus`.
##### `let:submitAttemptCount: number`
Number of times user tried to submit the form. Increases when `handleSubmit` is called, resets after calling `handleReset`.
##### `let:submitFailure: () => void`
Increment `submitFailureCount` by 1 and calls `setSubmitting(false)`.
##### `let:submitFailureCount: number`
Number of failed form submissions. Increases when `submitFailure` is called, resets after calling `handleReset`.
##### `let:submitForm: () => Promise`
Trigger a form submission. The promise will be rejected if form is invalid.
##### `let:submitSuccess: () => void`
Increment `submitSuccessCount` by 1 and calls `setSubmitting(false)`.
##### `let:submitSuccessCount: number`
Number of successful form submissions. Increases when `submitSuccess` is called, resets after calling `handleReset`.
##### `let:touched: { [field: string]: boolean }`
Touched fields. Each key corresponds to a field that has been touched/visited.
##### `let:values: { [field: string]: any }`
Your form's values.
##### `let:validateForm: (values?: any) => void`
Imperatively call `validate`. You can optionally pass values to validate against and this modify Sveltik state accordingly, otherwise this will use the current `values` of the form.
##### `let:validateField: (field: string) => void`
Imperatively call field's `validate` function if specified for given field. Sveltik will use the current field value.
##### `let:warnings: { [field: string]: string }`
Form warnings. Should match the shape of your form's values defined in `initialValues`.
#### Differences with Formik
- Validation is synchronous
- Includes support for field warnings with `warnings`, `setWarnings`, `setFieldWarning`
- Includes support for submission success/failure with `submitSuccess` and `submitFailure` helpers
- Tracks `submitAttemptCount`, `submitFailureCount` and `submitSuccessCount` instead of only `submitCount`
- If `onSubmit` returns a promise, it's rejection calls `submitFailure` and it's resolution calls `submitSuccess`
- Does not (yet) implement Yup or `validateSchema`## ``
`` will automagically hook up inputs to Sveltik. It uses the name attribute to match up with Sveltik state.
With no options passed, `` will default to an HTML `` element.### Example
[Open in REPL](https://svelte.dev/repl/47dade3d6be14be685c0347e0d525de7?version=3)
**MyInput.svelte**
```html
export let field
export let props```
**App.svelte**
```html
import { Sveltik, Form, Field } from 'sveltik'
import MyInput from './MyInput.svelte'
My Form
{
setTimeout(() => {
alert(JSON.stringify(values, null, 2))
actions.setSubmitting(false)
}, 1000)
}}
>
Red
Green
Blue
{#if meta.touched && meta.error}
{meta.error}
{/if}
Submit
```### Props
- `as?: string | Component`
- `name: string`
- `validate?: (value: any) => undefined | string`### let:props
- `let:field: FieldInputProps`
- `let:form: SveltikBag`
- `let:meta: FieldMetaProps`### Reference
#### Props
##### `as?: string | Component`
Either a Svelte component or the name of an HTML element to render. Supports the following:
- `input`
- `select`
- `textarea`Svelte components must `export let` the props that they expect to be passed.
The available props are match the let:props (see below). Also is passed an additional prop
`props` which contains all additional props passed to ``.##### `name: string`
A field's name in Sveltik state. Required.
##### `validate?: (value: any) => undefined | string`
You can run independent field-level validations by passing a function to the `validate` prop.
The function will respect the `validateOnBlur` and `validateOnChange` config/props specified in the ``'s parent ``.If invalid, return a `string` containing the error message or return `undefined`.
#### let:props
##### `let:field: FieldInputProps`
An object that contains:
- `name: string` - The name of the field
- `value: any` - The value of the field
- `handleInput: (e: HTMLInputEvent) => void` - Input handler to be bound with `on:input`
- `handleBlur: (e: HTMLBlurEvent) => void` - Blur handler to be bound with `on:blur`##### `let:form: SveltikBag`
##### `let:meta: FieldMetaProps`
An object that contains:
- `initialError?: string` - The field's initial error if the field is present in `initialErrors`
- `initialTouched?: boolean` - The field's initial value if the field is present in `initialTouched`
- `initialValue?: any` - The field's initial value if the field is given a value in `initialValues`
- `initialWarning?: string` - The field's initial warning if the field is given a value in `initialWarnings`
- `error?: string` - The field's error message
- `touched?: boolean` - Whether the field has been visited
- `value?: any` - The field's value
- `warning?: string` - The field's warning message#### Differences with Formik
- Validation is synchronous
- Event handlers must be set implictly with `on:input`, `on:blur` instead of spread attributes.
- Nested field names (paths) are not supported.## ``
Form is a small wrapper around an HTML `` element that automatically hooks into Sveltik's `handleSubmit` and `handleReset`.
All other props are passed directly through to the DOM node.```js
// so...// is identical to this...
```
## ``
`` is a component that renders the error message of a given field
if that field has been visited (i.e.`touched[name] === true`) (and there is an `error` message present).
It expects that all error messages are stored for a given field as a string.### Props
- `as?: string | Component`
- `name: string`### let:props
- `let:msg: string`
### Reference
#### Props
##### `as?: string | Component`
Either a Svelte component or the name of an HTML element to render.
If not specified, `` will just return a string.Svelte components must `export let` the props that they expect to be passed.
The available props are match the let:props (see below).
Also is passed an additional prop `props` which contains all additional props passed to ``.##### `name: string`
A field's name in Sveltik state. Required.
#### let:props
##### `let:msg: string`
A field's error message.
#### Differences with Formik
- Nested field names (paths) are not supported.
- Uses `as` prop instead of `component` for consistency with ``## ``
`` marks the DOM scroll position of a form element in the document.
It renders a zero-height div. Useful for scrolling to the first field with an error.### Props
- `name: string`
### Reference
#### Props
##### `name: string`
A field's name in Sveltik state. Required.