Validate and submit a form
Keep form values, validation and submission outcomes distinguishable.
Table of contents
APIs used
- mount
- Starts a Valyrian.js application on a DOM target.
- FormStore
- Coordinates form state, validation, transforms and submission.
Run this recipe
- Starting project
- Use the local TSX and ESM project from Stage 1 with Valyrian.js installed and its ESM browser build configured.
- File
- Replace src/client-entry.tsx with this recipe snippet.
- Run
- Run npm run build, serve public with npx --yes serve@14.2.5 public --listen 8000, open http://localhost:8000 and use the example's visible controls.
- Observable result
- A short name shows validationErrors. The value fail shows submitError. Any other valid name completes after the visible inflight state.
Starting point
Start with an editable profile whose name is required before saving.
Steps
Bind the form with v-form and its editable name with v-field. Submit records success, while the view exposes isDirty, isInflight and the last result.
tsximport { mount } from "valyrian.js";
import { FormStore } from "valyrian.js/forms";
const result = { submitted: null as boolean | null, savedName: "" };
const profileForm = new FormStore({
state: { name: "" },
schema: {
type: "object",
required: ["name"],
properties: { name: { type: "string", minLength: 2 } },
},
clean: { name: (value) => String(value).trim() },
onSubmit: async (values) => {
await new Promise((resolve) => setTimeout(resolve, 500));
if (values.name === "fail") {
throw new Error("Profile could not be saved");
}
result.savedName = values.name;
},
});
function ProfileForm() {
return (
<main>
<form
v-form={profileForm}
onsubmit={() => {
result.submitted = profileForm.success;
}}
>
<label>
Name
<input name="name" v-field={profileForm} />
</label>
<p v-if={profileForm.validationErrors.name}>
{profileForm.validationErrors.name}
</p>
<button type="submit" disabled={profileForm.isInflight}>
{profileForm.isInflight ? "Saving profile..." : "Save profile"}
</button>
</form>
<p>Dirty: {String(profileForm.isDirty)}</p>
<p>Last submit result: {String(result.submitted)}</p>
<p v-if={profileForm.submitError}>
{profileForm.submitError instanceof Error
? profileForm.submitError.message
: String(profileForm.submitError)}
</p>
<p v-if={profileForm.success}>Saved profile: {result.savedName}</p>
</main>
);
}
mount("body", ProfileForm);Result
A short name shows validationErrors. The value fail shows submitError. Any other valid name completes after the visible inflight state.
Limits
validationErrors and submitError expose validation and submission failures separately.