@sparkstone/solid-validation
Version:
A lightweight form validation library for Solid.js with PocketBase integration.
197 lines (141 loc) • 5.54 kB
Markdown
# @sparkstone/solid-validation
A lightweight and flexible form validation library for Solid.js. It provides a simple API to validate form inputs, handle submission state, and manage error messages.
## Installation
```sh
npm install @sparkstone/solid-validation
```
or
```sh
pnpm add @sparkstone/solid-validation
```
## Table of Contents
- [Usage](#usage)
- Basic Example
- [API](#api)
- `useForm(options?: { errorClass?: string })`
- `validate`
- `formSubmit`
- `errors`
- `isSubmitting`
- `isSubmitted`
- `validateRef`
- `validateField`
- `getFieldValue`
- [Custom Validation](#custom-validation)
- Example Validator
- [PocketBase Integration](#pocketbase-integration)
- `prepareFormDataForPocketbase`
- `parsePocketbaseError`
## Usage
### Basic Example
```tsx
import { createSignal } from 'solid-js';
import { useForm } from '@sparkstone/solid-validation';
function min5Characters(el: HTMLInputElement) {
if (el.value.length < 5) {
return 'must be at least 5 characters long';
}
}
function MyForm() {
const { formSubmit, validate, errors, isSubmitting, isSubmitted } = useForm();
async function onSubmit(form: HTMLFormElement) {
const formData = new FormData(form);
try {
// Submit form data here
} catch (e) {
return {
myCustomFormError: e.message,
};
}
}
return (
<form use:formSubmit={onSubmit}>
<input type='text' name='username' placeholder='Enter username' required use:validate />
<span>{errors.username}</span>
<input
type='text'
name='message'
placeholder='Enter message'
required
use:validate={[min5Characters]}
/>
<span>{errors.message}</span>
<span>{errors.myCustomFormError}</span>
<button type='submit' disabled={isSubmitting()}>
{isSubmitting() ? 'Submitting...' : 'Submit'}
</button>
{isSubmitted() && <p>Form successfully submitted!</p>}
</form>
);
}
function required(el: HTMLInputElement) {
return el.value.trim() ? false : 'This field is required';
}
```
## API
### `useForm(options?: { errorClass?: string })`
Creates a form validation context.
#### Returns:
- `validate(ref: HTMLInputElement, validators?: Validator[])`
Registers an input for validation.
- `formSubmit(ref: HTMLFormElement, callback: OnFormSubmit)`
Handles form submission, running all validations.
- `errors: Partial<Record<string, string>>`
Reactive store of validation errors.
- `isSubmitting: () => boolean`
Tracks whether the form is currently submitting.
- `isSubmitted: () => boolean`
Tracks whether the form was successfully submitted.
- `validateRef: (...args: Parameters<typeof validate>) => (ref: HTMLInputElement) => void`
If you're validating a custom element, you can pass this in with `ref={validateRef()}`.
- `validateField(fieldName: keyof ErrorFields): Promise<boolean>`
Validates a field based on its name. It returns `true` if the field is valid. If the field fails validation, it automatically focuses the field and updates the error state.
- `getFieldValue(fieldName: keyof ErrorFields)`
Retrieves the current value of the specified field. This is useful when you need to access a field’s value programmatically during form interactions.
### Custom Validation
A validator function receives an `HTMLInputElement` and returns:
- `false | "" | null | undefined` for valid inputs.
- A `string` error message for invalid inputs.
- A `Promise<string | Falsy>` for async validation.
Example:
```tsx
function minLength(el: HTMLInputElement) {
return el.value.length < 5 && 'Must be at least 5 characters';
}
```
## PocketBase Integration
For integrating form validation with [PocketBase](https://pocketbase.io/), this package provides helper functions to prepare form data and handle errors from PocketBase responses.
### `prepareFormDataForPocketbase(formData: FormData, form: HTMLFormElement)`
PocketBase does not include unchecked checkboxes in `FormData` submissions. This function ensures that all checkbox fields are included, defaulting to `"false"` if unchecked.
#### Example:
```ts
import { prepareFormDataForPocketbase } from '@sparkstone/solid-validation/pocketbase';
function handleSubmit(event: Event) {
event.preventDefault();
const form = event.currentTarget as HTMLFormElement;
const formData = new FormData(form);
prepareFormDataForPocketbase(formData, form);
// Now formData is ready to be sent to PocketBase
}
```
### `parsePocketbaseError(error: PocketbaseError, rootErrorKey = "form")`
PocketBase API errors return a structured `data` object. This function extracts error messages and formats them for easy use in your validation logic.
#### Example:
```ts
import { parsePocketbaseError } from '@sparkstone/solid-validation/pocketbase';
async function handleSubmit(event: Event) {
event.preventDefault();
const form = event.currentTarget as HTMLFormElement;
const formData = new FormData(form);
try {
// Replace with your PocketBase API call
await pocketbase.collection('users').create(formData);
} catch (e) {
const errors = parsePocketbaseError(e);
console.log(errors); // { email: "Invalid email", password: "Too short", form: "Something went wrong" }
}
}
```
This allows for easy mapping of errors to form fields and a general error message under the `"form"` key.
---
These functions help streamline form submissions and error handling when using PocketBase as your backend.