microform
is a tiny library for managing forms in svelte/sveltekit
.
# In your project directory
npm install @steveesamson/microform
or
# In your project directory
yarn add @steveesamson/microform
Once you've added microform
to your project, use it as shown below, in your view(.svelte
files):
<script lang='ts'>
import uForm from "@steveesamson/microform";
// default form data, probably passed as props
export let defaultData:any = {};
// Instatiate microform
const { form, values, errors, submit, valid } = uForm({
// Set default form data
data:{...defaultData},
// Set a global event for validation, can be overriden on a each field.
// Possible values: blur, change, input, keyup
validateEvent:'blur'
});
// Submit handler
// data is the collected form data
// Only called on valid form
// A form is valid when it has no error and at least one of the fields has changed
const onSubmit = (data:unknown) => {
console.log(data);
}
</script>
On the instantiation of microform
, we have access to:
values
, aFormValues
, which is asvelte store
for form data.errors
, aFormErrors
, which is asvelte store
for form errors.form
, which is asvelte action
that actually does themicroform
magic.submit
, which is anothersvelte action
to handle form submission.valid
, aFormSanity
, which is asvelte store
that tells if a form is clean/without errors.reset
, a function to reset formonsubmit
, a function to handle form submission.
<form use:submit={onSubmit}>
<label for='username'>
Username:
<input
type='text'
name='username'
id='username'
use:form
data-validations='required'>
{#if $errors.username}
<small>{$errors.username}</small>
{/if}
</label>
<label for='email_account'>
Email Account:
<input
type='text'
name='email_account'
id='email_account'
use:form={{
validations:'required|email'
}}/>
{#if $errors.email_account}
<small>{$errors.email_account}</small>
{/if}
</label>
<label for='gender'>
Gender:
<select
name='gender'
id='gender'
use:form={{
validations:'required',
validateEvent:'change'
}}>
<options value=''>Gender please</option>
<options value='F'>Female</option>
<options value='M'>Male</option>
</select>
{#if $errors.gender}
<small>{$errors.gender}</small>
{/if}
</label>
<label for='password'>
Password:
<input
type='text'
name='password'
id='password'
use:form
data-validations='required'>
{#if $errors.password}
<small>{$errors.password}</small>
{/if}
</label>
<label for='confirm_password'>
Confirm password:
<input
type='text'
name='confirm_password'
id='confirm_password'
use:form
data-validations='required|match:password'>
{#if $errors.confirm_password}
<small>{$errors.confirm_password}</small>
{/if}
</label>
<label for="story">
Story:
<div
contenteditable="true"
use:form={{
validateEvent: 'input',
validations: 'required',
name: 'story',
html: true
}}
/>
{#if $errors.story}
<small>{$errors.story}</small>
{/if}
</label>
<button
type='submit'
disabled={!$valid}>
Submit form
</button>
</form>
While the above example uses the submit
action of microform
, form could also be submitted by using the onsubmit
function of microform
. See the following:
<form>
<label for="password">
Password:
<input type="text" name="password" id="password" use:form data-validations="required" />
{#if $errors.password}
<small>{$errors.password}</small>
{/if}
</label>
<label for="confirm_password">
Confirm password:
<input
type="text"
name="confirm_password"
id="confirm_password"
use:form
data-validations="required|match:password"
/>
{#if $errors.confirm_password}
<small>{$errors.confirm_password}</small>
{/if}
</label>
<button type="button" disabled="{!$valid}" on:click="{onsubmit(onSubmit)}">Submit form</button>
</form>
microform
performs its magic by relying the form
action. The form
action can optionally accept the following:
<input
use:form={{
// an optional list of validations
// default is '' - no validations
validations: 'email|length:20',
// an optional string of
// any of blur, change, input, keyup.
// default is blur
validateEvent: 'input',
// an optional string that allows passing field names
// especially useful for contenteditables
// that have no native name attribute
// default is ''
name: '',
// an optional boolean indicating
// whether content should be treated as plain text or html
// also useful for contenteditables
// default is false
html: true
}}
/>
You need not bind the values
to your fields except when there is a definite need for it as form
will coordinate all value changes based on the data
passed at instantiation, if any. Therefore, constructs like the following might not be neccessary:
<input
type="text"
name="email_account"
id="email_account"
value="{$values.email_account}"
data-validations="required|email"
use:form
/>
Uses both inline data-validations
on field and validations
props on form
action. For instance, the following are perfectly identical:
<input
type='text'
name='email_account'
id='email_account'
data-validations='required|email'
use:form/>
<input
type='text'
name='email_account'
id='email_account'
use:form={{
validations:'required|email'
}}/>
Validation event can be changed/specified on a per-field basis. For instance, in our example, the global validateEvent
was set to blur
but we changed it on the select field to change
like so:
<select
name='gender'
id='gender'
use:form={{
validations:'required',
validateEvent:'change'
}}>
<options value=''>Gender please</option>
<options value='F'>Female</option>
<options value='M'>Male</option>
</select>
microform
supports contenteditable
out-of-box:
<form use:submit={onSubmit}>
<label for="story">
Story:
<div
contenteditable="true"
use:form={{
validateEvent: 'input',
validations: 'required',
name: 'story',
html: true
}}
/>
{#if $errors.story}
<small>{$errors.story}</small>
{/if}
</label>
</form>
microform
provides a set of usable validations out-of-box. The following is a list of provided validations:
required
: Usage,validations='required'
email
: Usage,validations='email'
url
: Usage,validations='url'
ip
: Usage,validations='ip'
length
: Usage,validations='length:40'
number
: Usage,validations='number'
integer
: Usage,validations='integer'
alpha
: Usage,validations='alpha'
- only alphabetsalphanum
: Usage,validations='alphanum'
- alphanumericmatch
: Usage,validations='match:<name-of-field-to-match>'
. For instance, this is examplified in our example withpassword
andconfirm_password
fieldsmin-length
: Usage,validations='min-length:6'
max-length
: Usage,validations='max-length:15'
max
: Usage,validations='max:25'
max-file-size-mb
: Usage,validations='max-file-size-mb:30'
- for file upload
Every validation listed above also comes with a very good default error message.
Finally, the validations can be combined to form a complex graph of validations based on use cases by separating each validation rule with a pipe
, |
. For instance, a required field that also should be an email field could be validated thus:
<input
type="text"
name="email_account"
id="email_account"
data-validations="required|email"
use:form
/>
I shall be working on how to allow users register their validators
and error messages
for the purpose of customisation.