Fully typed form state management library (with validation) for the VanJS framework. If you are coming
from React, vanjs-form
feels similar to react-hook-form.
yarn add vanjs-form vanjs-core yup
npm i -S vanjs-form vanjs-core yup
Form
API to create and manage the form stateimport van from "vanjs-core";
import { Form, yupValidator } from "vanjs-form";
import * as yup from "yup";
const { div, h1, p, input, label, select, form: formEl, button, br } = van.tags;
function App() {
const form = new Form({
initialValues: {
title: "",
name: "",
age: 0,
gender: ""
},
validator: yupValidator(
yup.object({
title: yup.string().required("Required"),
name: yup.string().required("Required"),
age: yup.number().required("Required").min(18, "At least 18 years"),
gender: yup.string().oneOf(["Male", "Female"], "Valid gender required")
})
),
validationMode: "oninput" // Validation is run on input as well as on submit. Defaults to 'onsubmit'
});
// Watch values when they change in the form fields
const observables = form.watch("name", "title");
// Called when form passes validation
const onsubmit = form.handleSubmit((values) => {
console.log({ submittedValues: values });
});
return div(
h1(() => `VanJS Form for ${observables.val.title} ${observables.val.name}`),
formEl(
{ onsubmit: onsubmit },
label("Title"),
div(
label(input(form.register("title", { type: "radio", value: "Mr." })), "Mr."),
label(input(form.register("title", { type: "radio", value: "Ms." })), "Ms."),
label(input(form.register("title", { type: "radio", value: "Mrs." })), "Mrs.")
),
br(),
label("Name"),
input(form.register("name", { autofocus: true })),
br(),
label("Age"),
input(form.register("age", { type: "number", min: "0", max: "100" })),
br(),
label("Gender"),
select(
form.register("gender", { type: "number", min: "0", max: "100" }),
option({ value: "" }, "Select..."),
option({ value: "Male" }, "Male"),
option({ value: "Female" }, "Female")
),
br(),
button({ type: "submit" }, "Submit")
)
);
}
van.add(document.body, App());
Form
class controls the form state and has methods to manipulate this statevalidator
parameter is provided, the submit handler is called if validation passesvalidationMode
to control whether validation should occur on input or only on submitimport { Form } from "vanjs-form";
const form = new Form({
initialValues: Record<string, any>,
validator: (values: Record<string, any>) => Record<string, any> | FormError,
validationMode: "onsubmit" | "oninput" // Defaults to onsubmit
});
After the instance is created, you can access the form functions to work with your form.
yupValidator
function takes a Yup ObjectSchema
and returns a validator
functionconst form = new Form({
initialValues: {
title: "",
name: "",
age: 0,
gender: ""
},
validator: yupValidator(
yup.object({
title: yup.string().required("Required"),
name: yup.string().required("Required"),
age: yup.number().required("Required").min(18, "At least 18 years"),
gender: yup.string().oneOf(["Male", "Female"], "Valid gender required")
})
)
});
import { Form } from "vanjs-form";
const form = new Form({
initialValues: Record<string, any>,
validator: (values: Record<string, any>) => Record<string, any> | FormError,
validationMode: "onsubmit" | "oninput" // Defaults to onsubmit
});
form.register();
form.get();
form.set();
form.error();
form.watch();
form.reset();
form.handleSubmit();
additionalProps
into returned objectname
, value
, checked
, oninput
, onfocus
) which should be spread unto the
input's propertiesform.register(name: string, additionalProps: Partial<HTMLElement>): HTMLElement;
name
in the formform.get(name: string): T[typeof name];
name
in the formform.set(name: string, value: T[typeof name]): void;
name
in the formform.error(name: string): string;
van.derive()
🙂form.watch(...names: string[]): State<{}>
form.reset(...name: string[]): void // Reset specific fields
form.reset(): void // Reset entire form
validator
is specified on the form, the handler is called if validation passesform.handleSubmit((values: T) => void): (values: T) => void
form.validateField
on form.reset
to avoid errors on form reset