From 3ae0043f48311db1b14fd4612d1ad7e3c714cd21 Mon Sep 17 00:00:00 2001 From: "svelte-docs-bot[bot]" <196124396+svelte-docs-bot[bot]@users.noreply.github.com> Date: Tue, 16 Sep 2025 21:39:53 +0000 Subject: [PATCH] sync kit docs --- .../20-core-concepts/60-remote-functions.md | 282 +++++++++++++++--- .../docs/kit/98-reference/10-@sveltejs-kit.md | 105 ++++++- .../docs/kit/98-reference/20-$app-server.md | 36 ++- 3 files changed, 361 insertions(+), 62 deletions(-) diff --git a/apps/svelte.dev/content/docs/kit/20-core-concepts/60-remote-functions.md b/apps/svelte.dev/content/docs/kit/20-core-concepts/60-remote-functions.md index 2d6364e690..ae9fd05324 100644 --- a/apps/svelte.dev/content/docs/kit/20-core-concepts/60-remote-functions.md +++ b/apps/svelte.dev/content/docs/kit/20-core-concepts/60-remote-functions.md @@ -228,7 +228,7 @@ export const getWeather = query.batch(v.string(), async (cities) => { ## form -The `form` function makes it easy to write data to the server. It takes a callback that receives the current [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData)... +The `form` function makes it easy to write data to the server. It takes a callback that receives `data` constructed from the submitted [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData)... ```ts @@ -260,30 +260,28 @@ export const getPosts = query(async () => { /* ... */ }); export const getPost = query(v.string(), async (slug) => { /* ... */ }); -export const createPost = form(async (data) => { - // Check the user is logged in - const user = await auth.getUser(); - if (!user) error(401, 'Unauthorized'); - - const title = data.get('title'); - const content = data.get('content'); - - // Check the data is valid - if (typeof title !== 'string' || typeof content !== 'string') { - error(400, 'Title and content are required'); +export const createPost = form( + v.object({ + title: v.pipe(v.string(), v.nonEmpty()), + content:v.pipe(v.string(), v.nonEmpty()) + }), + async ({ title, content }) => { + // Check the user is logged in + const user = await auth.getUser(); + if (!user) error(401, 'Unauthorized'); + + const slug = title.toLowerCase().replace(/ /g, '-'); + + // Insert into the database + await db.sql` + INSERT INTO post (slug, title, content) + VALUES (${slug}, ${title}, ${content}) + `; + + // Redirect to the newly created page + redirect(303, `/blog/${slug}`); } - - const slug = title.toLowerCase().replace(/ /g, '-'); - - // Insert into the database - await db.sql` - INSERT INTO post (slug, title, content) - VALUES (${slug}, ${title}, ${content}) - `; - - // Redirect to the newly created page - redirect(303, `/blog/${slug}`); -}); +); ``` ...and returns an object that can be spread onto a `
``` -The form object contains `method` and `action` properties that allow it to work without JavaScript (i.e. it submits data and reloads the page). It also has an `onsubmit` handler that progressively enhances the form when JavaScript is available, submitting data *without* reloading the entire page. +As with `query`, if the callback uses the submitted `data`, it should be [validated](#query-Query-arguments) by passing a [Standard Schema](https://standardschema.dev) as the first argument to `form`. The one difference is to `query` is that the schema inputs must all be of type `string` or `File`, since that's all the original `FormData` provides. You can however coerce the value into a different type — how to do that depends on the validation library you use. + +```ts +/// file: src/routes/count.remote.js +import * as v from 'valibot'; +import { form } from '$app/server'; + +export const setCount = form( + v.object({ + // Valibot: + count: v.pipe(v.string(), v.transform((s) => Number(s)), v.number()), + // Zod: + // count: v.coerce.number() + }), + async ({ count }) => { + // ... + } +); +``` + +The `name` attributes on the form controls must correspond to the properties of the schema — `title` and `content` in this case. If you schema contains objects, use object notation: + +```svelte + + + +{#each jobs as job, idx} + + +{/each} +``` + +To indicate a repeated field, use a `[]` suffix: + +```svelte + + + +``` + +If you'd like type safety and autocomplete when setting `name` attributes, use the form object's `field` method: + +```svelte + +``` + +This will error during typechecking if `title` does not exist on your schema. + +The form object contains `method` and `action` properties that allow it to work without JavaScript (i.e. it submits data and reloads the page). It also has an [attachment](/docs/svelte/@attach) that progressively enhances the form when JavaScript is available, submitting data *without* reloading the entire page. + +### Validation + +If the submitted data doesn't pass the schema, the callback will not run. Instead, the form object's `issues` object will be populated: + +```svelte + +``` + +You don't need to wait until the form is submitted to validate the data — you can call `validate()` programmatically, for example in an `oninput` callback (which will validate the data on every keystroke) or an `onchange` callback: + +```svelte + +``` + +By default, issues will be ignored if they belong to form controls that haven't yet been interacted with. To validate _all_ inputs, call `validate({ includeUntouched: true })`. + +For client-side validation, you can specify a _preflight_ schema which will populate `issues` and prevent data being sent to the server if the data doesn't validate: + +```svelte + + +