Skip to main content

Form actions

+page.server.js ファイルは actions をエクスポートできます。これによって、<form> 要素を使用することでサーバーにデータを POST することができます。

<form> を使用する場合、クライアントサイドの JavaScript はオプションですが、JavaScript によって form のインタラクションを簡単にプログレッシブに強化(progressively enhance)することができ、最高のユーザーエクスペリエンスを提供することができます。

Default actions

最もシンプルなケースでは、ページは default の action を宣言します:

src/routes/login/+page.server
/** @type {import('./$types').Actions} */
export const 
const actions: {
    default: (event: any) => Promise<void>;
}
@type{import('./$types').Actions}
actions
= {
default: (event: any) => Promise<void>default: async (event: anyevent) => { // TODO log the user in } };
import type { 
type Actions = {
    [x: string]: Kit.Action<Record<string, any>, void | Record<string, any>, string | null>;
}
type Actions = {
    [x: string]: Kit.Action<Record<string, any>, void | Record<string, any>, string | null>;
}
Actions
} from './$types';
export const const actions: Actionsactions:
type Actions = {
    [x: string]: Kit.Action<Record<string, any>, void | Record<string, any>, string | null>;
}
type Actions = {
    [x: string]: Kit.Action<Record<string, any>, void | Record<string, any>, string | null>;
}
Actions
= {
default: (event: Kit.RequestEvent<Record<string, any>, string | null>) => Promise<void>default: async (event: Kit.RequestEvent<Record<string, any>, string | null>event) => { // TODO log the user in } };

/login ページからこの action を呼び出すには、<form> を追加します。JavaScript は必要ありません:

src/routes/login/+page
<form method="POST">
	<label>
		Email
		<input name="email" type="email">
	</label>
	<label>
		Password
		<input name="password" type="password">
	</label>
	<button>Log in</button>
</form>

もし誰かがボタンをクリックしたら、ブラウザは form のデータを POST リクエストでサーバーに送信し、デフォルトの action が実行されます。

Action は常に POST リクエストを使用します。GET リクエストには決して副作用があってはならないからです。

また、action 属性を追加し、リクエスト先のページを指し示すことで、他のページから action を呼び出すこともできます (例えば、最上位のレイアウト(root layout)にある nav にログイン用の widget がある場合):

src/routes/+layout
<form method="POST" action="/login">
	<!-- content -->
</form>

Named actions

単一の default の action の代わりに、名前付きの action (named action) を必要なだけ持つことができます:

src/routes/login/+page.server
/** @satisfies {import('./$types').Actions} */
export const 
const actions: {
    login: (event: any) => Promise<void>;
    register: (event: any) => Promise<void>;
}
@satisfies{import('./$types').Actions}
actions
= {
default: async (event) => { login: (event: any) => Promise<void>login: async (event: anyevent) => { // TODO log the user in }, register: (event: any) => Promise<void>register: async (event: anyevent) => { // TODO register the user } };
import type { 
type Actions = {
    [x: string]: Kit.Action<Record<string, any>, void | Record<string, any>, string | null>;
}
type Actions = {
    [x: string]: Kit.Action<Record<string, any>, void | Record<string, any>, string | null>;
}
Actions
} from './$types';
export const
const actions: {
    login: (event: Kit.RequestEvent<Record<string, any>, string | null>) => Promise<void>;
    register: (event: Kit.RequestEvent<Record<string, any>, string | null>) => Promise<...>;
}
actions
= {
default: async (event) => { login: (event: Kit.RequestEvent<Record<string, any>, string | null>) => Promise<void>login: async (event: Kit.RequestEvent<Record<string, any>, string | null>event) => { // TODO log the user in }, register: (event: Kit.RequestEvent<Record<string, any>, string | null>) => Promise<void>register: async (event: Kit.RequestEvent<Record<string, any>, string | null>event) => { // TODO register the user } } satisfies
type Actions = {
    [x: string]: Kit.Action<Record<string, any>, void | Record<string, any>, string | null>;
}
type Actions = {
    [x: string]: Kit.Action<Record<string, any>, void | Record<string, any>, string | null>;
}
Actions
;

名前付きの action (named action) を呼び出すには、クエリパラメータに / を接頭辞に付与したその action の名前を追加します:

src/routes/login/+page
<form method="POST" action="?/register">
src/routes/+layout
<form method="POST" action="/login?/register">

action 属性と同じように、button の formaction 属性を使用することができ、こうすると親の <form> とは別の action に同じ form のデータを POST することができます:

src/routes/login/+page
<form method="POST" action="?/login">
	<label>
		Email
		<input name="email" type="email">
	</label>
	<label>
		Password
		<input name="password" type="password">
	</label>
	<button>Log in</button>
	<button formaction="?/register">Register</button>
</form>

名前付き action (named action) の隣にデフォルトの action を置くことはできません。なぜなら リダイレクト無しで名前付き action (named action) に POST をすると、クエリパラメータが URL に保持され、それ以降デフォルトの POST をしようとしても以前 POST した名前付き action (named action) を通ってしまうからです。

action の解剖学

action はそれぞれ RequestEvent オブジェクトを受け取って、request.formData() でデータを読み込むことができます。リクエスト (例えば、cookie をセットしてユーザーをログインさせるなど) を処理したあと、action は次の更新まで、対応するページでは form プロパティで、アプリ全体では $page.form で利用可能なデータで応答することができます。

src/routes/login/+page.server
import * as module "$lib/server/db"db from '$lib/server/db';

/** @type {import('./$types').PageServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
load
({ cookies: Cookies

Get or set cookies related to the current request

cookies
}) {
const const user: anyuser = await module "$lib/server/db"db.getUserFromSession(cookies: Cookies

Get or set cookies related to the current request

cookies
.Cookies.get(name: string, opts?: CookieParseOptions): string | undefined

Gets a cookie that was previously set with cookies.set, or from the request headers.

@paramname the name of the cookie
@paramopts the options, passed directly to cookie.parse. See documentation here
get
('sessionid'));
return { user: anyuser }; } /** @satisfies {import('./$types').Actions} */ export const
const actions: {
    login: ({ cookies, request }: RequestEvent<Record<string, any>, string | null>) => Promise<{
        success: boolean;
    }>;
    register: (event: RequestEvent<Record<string, any>, string | null>) => Promise<...>;
}
@satisfies{import('./$types').Actions}
actions
= {
login: ({ cookies, request }: RequestEvent<Record<string, any>, string | null>) => Promise<{
    success: boolean;
}>
login
: async ({ cookies: Cookies

Get or set cookies related to the current request

cookies
, request: Request

The original request object

request
}) => {
const const data: FormDatadata = await request: Request

The original request object

request
.Body.formData(): Promise<FormData>formData();
const const email: FormDataEntryValue | nullemail = const data: FormDatadata.FormData.get(name: string): FormDataEntryValue | nullget('email'); const const password: FormDataEntryValue | nullpassword = const data: FormDatadata.FormData.get(name: string): FormDataEntryValue | nullget('password'); const const user: anyuser = await module "$lib/server/db"db.getUser(const email: FormDataEntryValue | nullemail); cookies: Cookies

Get or set cookies related to the current request

cookies
.
Cookies.set(name: string, value: string, opts: CookieSerializeOptions & {
    path: string;
}): void

Sets a cookie. This will add a set-cookie header to the response, but also make the cookie available via cookies.get or cookies.getAll during the current request.

The httpOnly and secure options are true by default (except on http://localhost, where secure is false), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The sameSite option defaults to lax.

You must specify a path for the cookie. In most cases you should explicitly set path: '/' to make the cookie available throughout your app. You can use relative paths, or set path: '' to make the cookie only available on the current path and its children

@paramname the name of the cookie
@paramvalue the cookie value
@paramopts the options, passed directly to cookie.serialize. See documentation here
set
('sessionid', await module "$lib/server/db"db.createSession(const user: anyuser), { path: string

Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.4 Path Set-Cookie attribute } . By default, the path is considered the “default path”.

path
: '/' });
return { success: booleansuccess: true }; }, register: (event: RequestEvent<Record<string, any>, string | null>) => Promise<void>register: async (event: RequestEvent<Record<string, any>, string | null>event) => { // TODO register the user } };
import * as module "$lib/server/db"db from '$lib/server/db';
import type { type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad, 
type Actions = {
    [x: string]: Action<Record<string, any>, void | Record<string, any>, string | null>;
}
Actions
} from './$types';
export const const load: PageServerLoadload: type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad = async ({ cookies: Cookies

Get or set cookies related to the current request

cookies
}) => {
const const user: anyuser = await module "$lib/server/db"db.getUserFromSession(cookies: Cookies

Get or set cookies related to the current request

cookies
.Cookies.get(name: string, opts?: CookieParseOptions): string | undefined

Gets a cookie that was previously set with cookies.set, or from the request headers.

@paramname the name of the cookie
@paramopts the options, passed directly to cookie.parse. See documentation here
get
('sessionid'));
return { user: anyuser }; }; export const
const actions: {
    login: ({ cookies, request }: RequestEvent<Record<string, any>, string | null>) => Promise<{
        success: boolean;
    }>;
    register: (event: RequestEvent<Record<string, any>, string | null>) => Promise<...>;
}
actions
= {
login: ({ cookies, request }: RequestEvent<Record<string, any>, string | null>) => Promise<{
    success: boolean;
}>
login
: async ({ cookies: Cookies

Get or set cookies related to the current request

cookies
, request: Request

The original request object

request
}) => {
const const data: FormDatadata = await request: Request

The original request object

request
.Body.formData(): Promise<FormData>formData();
const const email: FormDataEntryValue | nullemail = const data: FormDatadata.FormData.get(name: string): FormDataEntryValue | nullget('email'); const const password: FormDataEntryValue | nullpassword = const data: FormDatadata.FormData.get(name: string): FormDataEntryValue | nullget('password'); const const user: anyuser = await module "$lib/server/db"db.getUser(const email: FormDataEntryValue | nullemail); cookies: Cookies

Get or set cookies related to the current request

cookies
.
Cookies.set(name: string, value: string, opts: CookieSerializeOptions & {
    path: string;
}): void

Sets a cookie. This will add a set-cookie header to the response, but also make the cookie available via cookies.get or cookies.getAll during the current request.

The httpOnly and secure options are true by default (except on http://localhost, where secure is false), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The sameSite option defaults to lax.

You must specify a path for the cookie. In most cases you should explicitly set path: '/' to make the cookie available throughout your app. You can use relative paths, or set path: '' to make the cookie only available on the current path and its children

@paramname the name of the cookie
@paramvalue the cookie value
@paramopts the options, passed directly to cookie.serialize. See documentation here
set
('sessionid', await module "$lib/server/db"db.createSession(const user: anyuser), { path: string

Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.4 Path Set-Cookie attribute } . By default, the path is considered the “default path”.

path
: '/' });
return { success: booleansuccess: true }; }, register: (event: RequestEvent<Record<string, any>, string | null>) => Promise<void>register: async (event: RequestEvent<Record<string, any>, string | null>event) => { // TODO register the user } } satisfies
type Actions = {
    [x: string]: Action<Record<string, any>, void | Record<string, any>, string | null>;
}
Actions
;
src/routes/login/+page
<script>
	/** @type {{ data: import('./$types').PageData, form: import('./$types').ActionData }} */
	let { data, form } = $props();
</script>

{#if form?.success}
	<!-- このメッセージは一時的なものです; form 送信に対するレスポンスとしてページがレンダリングされたため、存在しています。
	       ユーザーがリロードすると消えます。 -->
	<p>Successfully logged in! Welcome back, {data.user.name}</p>
{/if}
<script lang="ts">
	import type { PageData, ActionData } from './$types';

	let { data, form }: { data: PageData, form: ActionData } = $props();
</script>

{#if form?.success}
	<!-- このメッセージは一時的なものです; form 送信に対するレスポンスとしてページがレンダリングされたため、存在しています。
	       ユーザーがリロードすると消えます。 -->
	<p>Successfully logged in! Welcome back, {data.user.name}</p>
{/if}
Legacy mode

In Svelte 4, you’d use export let data and export let form instead to declare properties

Validation errors

無効なデータが原因でリクエストが処理できなかった場合、再試行できるようにするために、直前に送信した form の値とともに validation error をユーザーに返すことができます。fail 関数は、HTTP ステータスコード (通常、validation error の場合は 400 か 422) をデータとともに返します。ステータスコードは $page.status から使用することができ、data は form から使用することができます:

src/routes/login/+page.server
import { function fail(status: number): ActionFailure<undefined> (+1 overload)

Create an ActionFailure object.

@paramstatus The HTTP status code. Must be in the range 400-599.
fail
} from '@sveltejs/kit';
import * as module "$lib/server/db"db from '$lib/server/db'; /** @satisfies {import('./$types').Actions} */ export const
const actions: {
    login: ({ cookies, request }: RequestEvent<Record<string, any>, string | null>) => Promise<ActionFailure<{
        email: string | null;
        missing: boolean;
    }> | ActionFailure<{
        ...;
    }> | {
        ...;
    }>;
    register: (event: RequestEvent<...>) => Promise<...>;
}
@satisfies{import('./$types').Actions}
actions
= {
login: ({ cookies, request }: RequestEvent<Record<string, any>, string | null>) => Promise<ActionFailure<{
    email: string | null;
    missing: boolean;
}> | ActionFailure<{
    email: FormDataEntryValue;
    incorrect: boolean;
}> | {
    ...;
}>
login
: async ({ cookies: Cookies

Get or set cookies related to the current request

cookies
, request: Request

The original request object

request
}) => {
const const data: FormDatadata = await request: Request

The original request object

request
.Body.formData(): Promise<FormData>formData();
const const email: FormDataEntryValue | nullemail = const data: FormDatadata.FormData.get(name: string): FormDataEntryValue | nullget('email'); const const password: FormDataEntryValue | nullpassword = const data: FormDatadata.FormData.get(name: string): FormDataEntryValue | nullget('password'); if (!const email: FormDataEntryValue | nullemail) { return
fail<{
    email: string | null;
    missing: boolean;
}>(status: number, data: {
    email: string | null;
    missing: boolean;
}): ActionFailure<{
    email: string | null;
    missing: boolean;
}> (+1 overload)

Create an ActionFailure object.

@paramstatus The HTTP status code. Must be in the range 400-599.
@paramdata Data associated with the failure (e.g. validation errors)
fail
(400, { email: string | nullemail, missing: booleanmissing: true });
} const const user: anyuser = await module "$lib/server/db"db.getUser(const email: FormDataEntryValueemail); if (!const user: anyuser || const user: anyuser.password !== module "$lib/server/db"db.hash(const password: FormDataEntryValue | nullpassword)) { return
fail<{
    email: FormDataEntryValue;
    incorrect: boolean;
}>(status: number, data: {
    email: FormDataEntryValue;
    incorrect: boolean;
}): ActionFailure<{
    email: FormDataEntryValue;
    incorrect: boolean;
}> (+1 overload)

Create an ActionFailure object.

@paramstatus The HTTP status code. Must be in the range 400-599.
@paramdata Data associated with the failure (e.g. validation errors)
fail
(400, { email: FormDataEntryValueemail, incorrect: booleanincorrect: true });
} cookies: Cookies

Get or set cookies related to the current request

cookies
.
Cookies.set(name: string, value: string, opts: CookieSerializeOptions & {
    path: string;
}): void

Sets a cookie. This will add a set-cookie header to the response, but also make the cookie available via cookies.get or cookies.getAll during the current request.

The httpOnly and secure options are true by default (except on http://localhost, where secure is false), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The sameSite option defaults to lax.

You must specify a path for the cookie. In most cases you should explicitly set path: '/' to make the cookie available throughout your app. You can use relative paths, or set path: '' to make the cookie only available on the current path and its children

@paramname the name of the cookie
@paramvalue the cookie value
@paramopts the options, passed directly to cookie.serialize. See documentation here
set
('sessionid', await module "$lib/server/db"db.createSession(const user: anyuser), { path: string

Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.4 Path Set-Cookie attribute } . By default, the path is considered the “default path”.

path
: '/' });
return { success: booleansuccess: true }; }, register: (event: RequestEvent<Record<string, any>, string | null>) => Promise<void>register: async (event: RequestEvent<Record<string, any>, string | null>event) => { // TODO register the user } };
import { function fail(status: number): ActionFailure<undefined> (+1 overload)

Create an ActionFailure object.

@paramstatus The HTTP status code. Must be in the range 400-599.
fail
} from '@sveltejs/kit';
import * as module "$lib/server/db"db from '$lib/server/db'; import type {
type Actions = {
    [x: string]: Action<Record<string, any>, void | Record<string, any>, string | null>;
}
Actions
} from './$types';
export const
const actions: {
    login: ({ cookies, request }: RequestEvent<Record<string, any>, string | null>) => Promise<ActionFailure<{
        email: string | null;
        missing: boolean;
    }> | ActionFailure<{
        ...;
    }> | {
        ...;
    }>;
    register: (event: RequestEvent<...>) => Promise<...>;
}
actions
= {
login: ({ cookies, request }: RequestEvent<Record<string, any>, string | null>) => Promise<ActionFailure<{
    email: string | null;
    missing: boolean;
}> | ActionFailure<{
    email: FormDataEntryValue;
    incorrect: boolean;
}> | {
    ...;
}>
login
: async ({ cookies: Cookies

Get or set cookies related to the current request

cookies
, request: Request

The original request object

request
}) => {
const const data: FormDatadata = await request: Request

The original request object

request
.Body.formData(): Promise<FormData>formData();
const const email: FormDataEntryValue | nullemail = const data: FormDatadata.FormData.get(name: string): FormDataEntryValue | nullget('email'); const const password: FormDataEntryValue | nullpassword = const data: FormDatadata.FormData.get(name: string): FormDataEntryValue | nullget('password'); if (!const email: FormDataEntryValue | nullemail) { return
fail<{
    email: string | null;
    missing: boolean;
}>(status: number, data: {
    email: string | null;
    missing: boolean;
}): ActionFailure<{
    email: string | null;
    missing: boolean;
}> (+1 overload)

Create an ActionFailure object.

@paramstatus The HTTP status code. Must be in the range 400-599.
@paramdata Data associated with the failure (e.g. validation errors)
fail
(400, { email: string | nullemail, missing: booleanmissing: true });
} const const user: anyuser = await module "$lib/server/db"db.getUser(const email: FormDataEntryValueemail); if (!const user: anyuser || const user: anyuser.password !== module "$lib/server/db"db.hash(const password: FormDataEntryValue | nullpassword)) { return
fail<{
    email: FormDataEntryValue;
    incorrect: boolean;
}>(status: number, data: {
    email: FormDataEntryValue;
    incorrect: boolean;
}): ActionFailure<{
    email: FormDataEntryValue;
    incorrect: boolean;
}> (+1 overload)

Create an ActionFailure object.

@paramstatus The HTTP status code. Must be in the range 400-599.
@paramdata Data associated with the failure (e.g. validation errors)
fail
(400, { email: FormDataEntryValueemail, incorrect: booleanincorrect: true });
} cookies: Cookies

Get or set cookies related to the current request

cookies
.
Cookies.set(name: string, value: string, opts: CookieSerializeOptions & {
    path: string;
}): void

Sets a cookie. This will add a set-cookie header to the response, but also make the cookie available via cookies.get or cookies.getAll during the current request.

The httpOnly and secure options are true by default (except on http://localhost, where secure is false), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The sameSite option defaults to lax.

You must specify a path for the cookie. In most cases you should explicitly set path: '/' to make the cookie available throughout your app. You can use relative paths, or set path: '' to make the cookie only available on the current path and its children

@paramname the name of the cookie
@paramvalue the cookie value
@paramopts the options, passed directly to cookie.serialize. See documentation here
set
('sessionid', await module "$lib/server/db"db.createSession(const user: anyuser), { path: string

Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.4 Path Set-Cookie attribute } . By default, the path is considered the “default path”.

path
: '/' });
return { success: booleansuccess: true }; }, register: (event: RequestEvent<Record<string, any>, string | null>) => Promise<void>register: async (event: RequestEvent<Record<string, any>, string | null>event) => { // TODO register the user } } satisfies
type Actions = {
    [x: string]: Action<Record<string, any>, void | Record<string, any>, string | null>;
}
Actions
;

念のため、password は返さず、email のみをページに返していることにご注意ください。

src/routes/login/+page
<form method="POST" action="?/login">
	{#if form?.missing}<p class="error">The email field is required</p>{/if}
	{#if form?.incorrect}<p class="error">Invalid credentials!</p>{/if}
	<label>
		Email
		<input name="email" type="email" value={form?.email ?? ''}>
	</label>
	<label>
		Password
		<input name="password" type="password">
	</label>
	<button>Log in</button>
	<button formaction="?/register">Register</button>
</form>

戻り値は JSON としてシリアライズ可能でなければなりません。その上で、構造は完全にあなた次第です。例えば、もしページに複数の form がある場合、返された form データがどの <form> を参照しているかを id プロパティなどで区別することができます。

Redirects

redirect (と error) は load のそれと同じように機能します:

src/routes/login/+page.server
import { function fail(status: number): ActionFailure<undefined> (+1 overload)

Create an ActionFailure object.

@paramstatus The HTTP status code. Must be in the range 400-599.
fail
, function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 300-308.
@paramlocation The location to redirect to.
@throwsRedirect This error instructs SvelteKit to redirect to the specified location.
@throwsError If the provided status is invalid.
redirect
} from '@sveltejs/kit';
import * as module "$lib/server/db"db from '$lib/server/db'; /** @satisfies {import('./$types').Actions} */ export const
const actions: {
    login: ({ cookies, request, url }: RequestEvent<Record<string, any>, string | null>) => Promise<ActionFailure<{
        email: FormDataEntryValue | null;
        missing: boolean;
    }> | ActionFailure<...> | {
        ...;
    }>;
    register: (event: RequestEvent<...>) => Promise<...>;
}
@satisfies{import('./$types').Actions}
actions
= {
login: ({ cookies, request, url }: RequestEvent<Record<string, any>, string | null>) => Promise<ActionFailure<{
    email: FormDataEntryValue | null;
    missing: boolean;
}> | ActionFailure<...> | {
    ...;
}>
login
: async ({ cookies: Cookies

Get or set cookies related to the current request

cookies
, request: Request

The original request object

request
, url: URL

The requested URL.

url
}) => {
const const data: FormDatadata = await request: Request

The original request object

request
.Body.formData(): Promise<FormData>formData();
const const email: FormDataEntryValue | nullemail = const data: FormDatadata.FormData.get(name: string): FormDataEntryValue | nullget('email'); const const password: FormDataEntryValue | nullpassword = const data: FormDatadata.FormData.get(name: string): FormDataEntryValue | nullget('password'); const const user: anyuser = await module "$lib/server/db"db.getUser(const email: FormDataEntryValue | nullemail); if (!const user: anyuser) { return
fail<{
    email: FormDataEntryValue | null;
    missing: boolean;
}>(status: number, data: {
    email: FormDataEntryValue | null;
    missing: boolean;
}): ActionFailure<...> (+1 overload)

Create an ActionFailure object.

@paramstatus The HTTP status code. Must be in the range 400-599.
@paramdata Data associated with the failure (e.g. validation errors)
fail
(400, { email: FormDataEntryValue | nullemail, missing: booleanmissing: true });
} if (const user: anyuser.password !== module "$lib/server/db"db.hash(const password: FormDataEntryValue | nullpassword)) { return
fail<{
    email: FormDataEntryValue | null;
    incorrect: boolean;
}>(status: number, data: {
    email: FormDataEntryValue | null;
    incorrect: boolean;
}): ActionFailure<...> (+1 overload)

Create an ActionFailure object.

@paramstatus The HTTP status code. Must be in the range 400-599.
@paramdata Data associated with the failure (e.g. validation errors)
fail
(400, { email: FormDataEntryValue | nullemail, incorrect: booleanincorrect: true });
} cookies: Cookies

Get or set cookies related to the current request

cookies
.
Cookies.set(name: string, value: string, opts: CookieSerializeOptions & {
    path: string;
}): void

Sets a cookie. This will add a set-cookie header to the response, but also make the cookie available via cookies.get or cookies.getAll during the current request.

The httpOnly and secure options are true by default (except on http://localhost, where secure is false), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The sameSite option defaults to lax.

You must specify a path for the cookie. In most cases you should explicitly set path: '/' to make the cookie available throughout your app. You can use relative paths, or set path: '' to make the cookie only available on the current path and its children

@paramname the name of the cookie
@paramvalue the cookie value
@paramopts the options, passed directly to cookie.serialize. See documentation here
set
('sessionid', await module "$lib/server/db"db.createSession(const user: anyuser), { path: string

Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.4 Path Set-Cookie attribute } . By default, the path is considered the “default path”.

path
: '/' });
if (url: URL

The requested URL.

url
.URL.searchParams: URLSearchParamssearchParams.URLSearchParams.has(name: string, value?: string): boolean

Returns a Boolean indicating if such a search parameter exists.

MDN Reference

has
('redirectTo')) {
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 300-308.
@paramlocation The location to redirect to.
@throwsRedirect This error instructs SvelteKit to redirect to the specified location.
@throwsError If the provided status is invalid.
redirect
(303, url: URL

The requested URL.

url
.URL.searchParams: URLSearchParamssearchParams.URLSearchParams.get(name: string): string | null

Returns the first value associated to the given search parameter.

MDN Reference

get
('redirectTo'));
} return { success: booleansuccess: true }; }, register: (event: RequestEvent<Record<string, any>, string | null>) => Promise<void>register: async (event: RequestEvent<Record<string, any>, string | null>event) => { // TODO register the user } };
import { function fail(status: number): ActionFailure<undefined> (+1 overload)

Create an ActionFailure object.

@paramstatus The HTTP status code. Must be in the range 400-599.
fail
, function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 300-308.
@paramlocation The location to redirect to.
@throwsRedirect This error instructs SvelteKit to redirect to the specified location.
@throwsError If the provided status is invalid.
redirect
} from '@sveltejs/kit';
import * as module "$lib/server/db"db from '$lib/server/db'; import type {
type Actions = {
    [x: string]: Action<Record<string, any>, void | Record<string, any>, string | null>;
}
Actions
} from './$types';
export const
const actions: {
    login: ({ cookies, request, url }: RequestEvent<Record<string, any>, string | null>) => Promise<ActionFailure<{
        email: FormDataEntryValue | null;
        missing: boolean;
    }> | ActionFailure<...> | {
        ...;
    }>;
    register: (event: RequestEvent<...>) => Promise<...>;
}
actions
= {
login: ({ cookies, request, url }: RequestEvent<Record<string, any>, string | null>) => Promise<ActionFailure<{
    email: FormDataEntryValue | null;
    missing: boolean;
}> | ActionFailure<...> | {
    ...;
}>
login
: async ({ cookies: Cookies

Get or set cookies related to the current request

cookies
, request: Request

The original request object

request
, url: URL

The requested URL.

url
}) => {
const const data: FormDatadata = await request: Request

The original request object

request
.Body.formData(): Promise<FormData>formData();
const const email: FormDataEntryValue | nullemail = const data: FormDatadata.FormData.get(name: string): FormDataEntryValue | nullget('email'); const const password: FormDataEntryValue | nullpassword = const data: FormDatadata.FormData.get(name: string): FormDataEntryValue | nullget('password'); const const user: anyuser = await module "$lib/server/db"db.getUser(const email: FormDataEntryValue | nullemail); if (!const user: anyuser) { return
fail<{
    email: FormDataEntryValue | null;
    missing: boolean;
}>(status: number, data: {
    email: FormDataEntryValue | null;
    missing: boolean;
}): ActionFailure<...> (+1 overload)

Create an ActionFailure object.

@paramstatus The HTTP status code. Must be in the range 400-599.
@paramdata Data associated with the failure (e.g. validation errors)
fail
(400, { email: FormDataEntryValue | nullemail, missing: booleanmissing: true });
} if (const user: anyuser.password !== module "$lib/server/db"db.hash(const password: FormDataEntryValue | nullpassword)) { return
fail<{
    email: FormDataEntryValue | null;
    incorrect: boolean;
}>(status: number, data: {
    email: FormDataEntryValue | null;
    incorrect: boolean;
}): ActionFailure<...> (+1 overload)

Create an ActionFailure object.

@paramstatus The HTTP status code. Must be in the range 400-599.
@paramdata Data associated with the failure (e.g. validation errors)
fail
(400, { email: FormDataEntryValue | nullemail, incorrect: booleanincorrect: true });
} cookies: Cookies

Get or set cookies related to the current request

cookies
.
Cookies.set(name: string, value: string, opts: CookieSerializeOptions & {
    path: string;
}): void

Sets a cookie. This will add a set-cookie header to the response, but also make the cookie available via cookies.get or cookies.getAll during the current request.

The httpOnly and secure options are true by default (except on http://localhost, where secure is false), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The sameSite option defaults to lax.

You must specify a path for the cookie. In most cases you should explicitly set path: '/' to make the cookie available throughout your app. You can use relative paths, or set path: '' to make the cookie only available on the current path and its children

@paramname the name of the cookie
@paramvalue the cookie value
@paramopts the options, passed directly to cookie.serialize. See documentation here
set
('sessionid', await module "$lib/server/db"db.createSession(const user: anyuser), { path: string

Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.4 Path Set-Cookie attribute } . By default, the path is considered the “default path”.

path
: '/' });
if (url: URL

The requested URL.

url
.URL.searchParams: URLSearchParamssearchParams.URLSearchParams.has(name: string, value?: string): boolean

Returns a Boolean indicating if such a search parameter exists.

MDN Reference

has
('redirectTo')) {
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 300-308.
@paramlocation The location to redirect to.
@throwsRedirect This error instructs SvelteKit to redirect to the specified location.
@throwsError If the provided status is invalid.
redirect
(303, url.searchParams.get('redirectTo'));
} return { success: booleansuccess: true }; }, register: (event: RequestEvent<Record<string, any>, string | null>) => Promise<void>register: async (event: RequestEvent<Record<string, any>, string | null>event) => { // TODO register the user } } satisfies
type Actions = {
    [x: string]: Action<Record<string, any>, void | Record<string, any>, string | null>;
}
Actions
;

Loading data

action の実行後、そのページは (リダイレクトや予期せぬエラーが発生しない限り) 再レンダリングされ、action の戻り値が form プロパティとしてそのページで使用できるようになります。つまり、ページの load 関数は、action が完了したあとに実行されるということです。

handle は action が呼び出される前に実行され、load 関数より前に再実行されることはないことに注意してください。つまり、例えば handle を使用して cookie を元に event.locals に値を入れる場合、action で cookie を設定したり削除したりするときは event.locals を更新しなければなりません:

src/hooks.server
/** @type {import('@sveltejs/kit').Handle} */
export async function 
function handle(input: {
    event: RequestEvent;
    resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
}): MaybePromise<...>
@type{import('@sveltejs/kit').Handle}
handle
({ event: RequestEvent<Partial<Record<string, string>>, string | null>event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve }) {
event: RequestEvent<Partial<Record<string, string>>, string | null>event.RequestEvent<Partial<Record<string, string>>, string | null>.locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user: {
    name: string;
} | null
user
= await
function getUser(sessionid: string | undefined): {
    name: string;
}
getUser
(event: RequestEvent<Partial<Record<string, string>>, string | null>event.RequestEvent<Partial<Record<string, string>>, string | null>.cookies: Cookies

Get or set cookies related to the current request

cookies
.Cookies.get(name: string, opts?: CookieParseOptions): string | undefined

Gets a cookie that was previously set with cookies.set, or from the request headers.

@paramname the name of the cookie
@paramopts the options, passed directly to cookie.parse. See documentation here
get
('sessionid'));
return resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve(event: RequestEvent<Partial<Record<string, string>>, string | null>event); }
import type { 
type Handle = (input: {
    event: RequestEvent;
    resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
}) => MaybePromise<...>

The handle hook runs every time the SvelteKit server receives a request and determines the response. It receives an event object representing the request and a function called resolve, which renders the route and generates a Response. This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).

Handle
} from '@sveltejs/kit';
export const const handle: Handlehandle:
type Handle = (input: {
    event: RequestEvent;
    resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
}) => MaybePromise<...>

The handle hook runs every time the SvelteKit server receives a request and determines the response. It receives an event object representing the request and a function called resolve, which renders the route and generates a Response. This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).

Handle
= async ({ event: RequestEvent<Partial<Record<string, string>>, string | null>event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve }) => {
event: RequestEvent<Partial<Record<string, string>>, string | null>event.RequestEvent<Partial<Record<string, string>>, string | null>.locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user: {
    name: string;
} | null
user
= await
function getUser(sessionid: string | undefined): {
    name: string;
}
getUser
(event: RequestEvent<Partial<Record<string, string>>, string | null>event.RequestEvent<Partial<Record<string, string>>, string | null>.cookies: Cookies

Get or set cookies related to the current request

cookies
.Cookies.get(name: string, opts?: CookieParseOptions): string | undefined

Gets a cookie that was previously set with cookies.set, or from the request headers.

@paramname the name of the cookie
@paramopts the options, passed directly to cookie.parse. See documentation here
get
('sessionid'));
return resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve(event: RequestEvent<Partial<Record<string, string>>, string | null>event); };
src/routes/account/+page.server
/** @type {import('./$types').PageServerLoad} */
export function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
load
(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>event) {
return {
user: {
    name: string;
} | null
user
: event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>event.RequestEvent<Record<string, any>, string | null>.locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user: {
    name: string;
} | null
user
}; } /** @satisfies {import('./$types').Actions} */ export const
const actions: {
    logout: (event: RequestEvent<Record<string, any>, string | null>) => Promise<void>;
}
@satisfies{import('./$types').Actions}
actions
= {
logout: (event: RequestEvent<Record<string, any>, string | null>) => Promise<void>logout: async (event: RequestEvent<Record<string, any>, string | null>event) => { event: RequestEvent<Record<string, any>, string | null>event.RequestEvent<Record<string, any>, string | null>.cookies: Cookies

Get or set cookies related to the current request

cookies
.
Cookies.delete(name: string, opts: CookieSerializeOptions & {
    path: string;
}): void

Deletes a cookie by setting its value to an empty string and setting the expiry date in the past.

You must specify a path for the cookie. In most cases you should explicitly set path: '/' to make the cookie available throughout your app. You can use relative paths, or set path: '' to make the cookie only available on the current path and its children

@paramname the name of the cookie
@paramopts the options, passed directly to cookie.serialize. The path must match the path of the cookie you want to delete. See documentation here
delete
('sessionid', { path: string

Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.4 Path Set-Cookie attribute } . By default, the path is considered the “default path”.

path
: '/' });
event: RequestEvent<Record<string, any>, string | null>event.RequestEvent<Params extends Partial<Record<string, string>> = Partial<Record<string, string>>, RouteId extends string | null = string | null>.locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user: {
    name: string;
} | null
user
= null;
} };
import type { type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad, 
type Actions = {
    [x: string]: Action<Record<string, any>, void | Record<string, any>, string | null>;
}
Actions
} from './$types';
export const const load: PageServerLoadload: type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>event) => { return {
user: {
    name: string;
} | null
user
: event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>event.RequestEvent<Record<string, any>, string | null>.locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user: {
    name: string;
} | null
user
}; }; export const
const actions: {
    logout: (event: RequestEvent<Record<string, any>, string | null>) => Promise<void>;
}
actions
= {
logout: (event: RequestEvent<Record<string, any>, string | null>) => Promise<void>logout: async (event: RequestEvent<Record<string, any>, string | null>event) => { event: RequestEvent<Record<string, any>, string | null>event.RequestEvent<Record<string, any>, string | null>.cookies: Cookies

Get or set cookies related to the current request

cookies
.
Cookies.delete(name: string, opts: CookieSerializeOptions & {
    path: string;
}): void

Deletes a cookie by setting its value to an empty string and setting the expiry date in the past.

You must specify a path for the cookie. In most cases you should explicitly set path: '/' to make the cookie available throughout your app. You can use relative paths, or set path: '' to make the cookie only available on the current path and its children

@paramname the name of the cookie
@paramopts the options, passed directly to cookie.serialize. The path must match the path of the cookie you want to delete. See documentation here
delete
('sessionid', { path: string

Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.4 Path Set-Cookie attribute } . By default, the path is considered the “default path”.

path
: '/' });
event: RequestEvent<Record<string, any>, string | null>event.RequestEvent<Params extends Partial<Record<string, string>> = Partial<Record<string, string>>, RouteId extends string | null = string | null>.locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user: {
    name: string;
} | null
user
= null;
} } satisfies
type Actions = {
    [x: string]: Action<Record<string, any>, void | Record<string, any>, string | null>;
}
Actions
;

Progressive enhancement

前のセクションでは クライアントサイドの JavaScriptなしで動作する /login action を構築しました — fetch は見当たりません。これは素晴らしいことですが、JavaScript が利用可能な場合は、より良いユーザーエクスペリンスを提供するために form のインタラクションをプログレッシブに強化 (progressively enhance) することができます。

use:enhance

form をプログレッシブに強化する最も簡単な方法は、use:enhance action を追加することです:

src/routes/login/+page
<script>
	import { enhance } from '$app/forms';

	/** @type {{ form: import('./$types').ActionData }} */
	let { form } = $props();
</script>

<form method="POST" use:enhance>
<script lang="ts">
	import { enhance } from '$app/forms';
	import type { ActionData } from './$types';

	let { form }: { form: ActionData } = $props();
</script>

<form method="POST" use:enhance>

use:enhance can only be used with forms that have method="POST". It will not work with method="GET", which is the default for forms without a specified method. Attempting to use use:enhance on forms without method="POST" will result in an error.

ええ、enhance action と <form action> をどちらも ‘action’ と呼んでいて、少し紛らわしいですよね。このドキュメントは action でいっぱいです。申し訳ありません。

引数が無い場合、use:enhance は、ブラウザネイティブの動作を、フルページリロードを除いてエミュレートします。それは:

  • action が送信元のページと同じ場所にある場合に限り、成功レスポンスまたは不正なレスポンスに応じて、form プロパティと $page.form$page.status を更新します。例えば、<form action="/somewhere/else" ..> というようなフォームの場合、form$page は更新されません。これは、ネイティブのフォーム送信では action があるページにリダイレクトされるからです。どちらにしても更新させたい場合は、applyAction を使用してください
  • <form> 要素をリセットします
  • 成功レスポンスの場合は invalidateAll で全てのデータを無効化・最新化(invalidate)します
  • リダイレクトレスポンスの場合は goto を呼び出します
  • エラーが発生した場合はもっとも近くにある +error 境界をレンダリングします
  • 適切な要素に フォーカスをリセット します

use:enhance をカスタマイズする

この挙動をカスタマイズするために、form が送信される直前に実行される SubmitFunction 関数を提供することができます。そして (オプションで) ActionResult を引数に取るコールバックを返すことができます。もしコールバックを返す場合、上述のデフォルトの動作はトリガーされません。元に戻すには、update を呼び出してください。

<form
	method="POST"
	use:enhance={({ formElement, formData, action, cancel, submitter }) => {
		// `formElement` はこの `<form>` 要素です
		// `formData` は送信される予定の `FormData` オブジェクトです
		// `action` はフォームが POST される URL です
		// `cancel()` を呼び出すと送信(submission)を中止します
		// `submitter` は、フォームの送信を実行した `HTMLElement` です

		return async ({ result, update }) => {
			// `result` は `ActionResult` オブジェクトです
			// `update` は、このコールバックが設定されていない場合に起動されるデフォルトのロジックを起動する関数です
		};
	}}
>

これらの関数を、ロード中の UI (loading UI) を表示したり隠したりすることなどに使用できます。

コールバックを返す場合は use:enhance のデフォルトの動作の一部を再現させる必要があるかもしれませんが、成功レスポンスで全てのデータを無効化・最新化(invalidate)する必要はありません。このような場合には applyAction を使用するとよいでしょう:

src/routes/login/+page
<script>
	import { enhance, applyAction } from '$app/forms';

	/** @type {{ form: import('./$types').ActionData }} */
	let { form } = $props();
</script>

<form
	method="POST"
	use:enhance={({ formElement, formData, action, cancel }) => {
		return async ({ result }) => {
			// `result` は `ActionResult` オブジェクトです
			if (result.type === 'redirect') {
				goto(result.location);
			} else {
				await applyAction(result);
			}
		};
	}}
>
<script lang="ts">
	import { enhance, applyAction } from '$app/forms';
	import type { ActionData } from './$types';

	let { form }: { form: ActionData } = $props();
</script>

<form
	method="POST"
	use:enhance={({ formElement, formData, action, cancel }) => {
		return async ({ result }) => {
			// `result` は `ActionResult` オブジェクトです
			if (result.type === 'redirect') {
				goto(result.location);
			} else {
				await applyAction(result);
			}
		};
	}}
>

applyAction(result) の挙動は result.type に依存しています:

  • success, failure$page.statusresult.status に設定し、form$page.formresult.data で更新します (enhanceupdate とは対照的に、送信元がどこかは関係ありません)
  • redirectgoto(result.location, { invalidateAll: true }) を呼び出します
  • error — もっとも近くにある +error 境界を result.error でレンダリングします

いずれの場合でも、フォーカスはリセットされます

Custom event listener

use:enhance ではなく、<form> の通常のイベントリスナーを使うことで、ご自身でプログレッシブ・エンハンスメント(progressive enhancement)を実装することもできます:

src/routes/login/+page
<script>
	import { invalidateAll, goto } from '$app/navigation';
	import { applyAction, deserialize } from '$app/forms';

	/** @type {{ form: import('./$types').ActionData }} */
	let { form } = $props();

	/** @param {{ currentTarget: EventTarget & HTMLFormElement}} event */
	async function handleSubmit(event) {
		const data = new FormData(event.currentTarget);

		const response = await fetch(event.currentTarget.action, {
			method: 'POST',
			body: data
		});

		/** @type {import('@sveltejs/kit').ActionResult} */
		const result = deserialize(await response.text());

		if (result.type === 'success') {
			// rerun all `load` functions, following the successful update
			await invalidateAll();
		}

		applyAction(result);
	}
</script>

<form method="POST" on:submit|preventDefault={handleSubmit}>
	<!-- content -->
</form>
<script lang="ts">
	import { invalidateAll, goto } from '$app/navigation';
	import { applyAction, deserialize } from '$app/forms';
	import type { ActionData } from './$types';
	import type { ActionResult } from '@sveltejs/kit';

	let { form }: { form: ActionData } = $props();

	async function handleSubmit(event: { currentTarget: EventTarget & HTMLFormElement}) {
		const data = new FormData(event.currentTarget);

		const response = await fetch(event.currentTarget.action, {
			method: 'POST',
			body: data
		});

		const result: ActionResult = deserialize(await response.text());

		if (result.type === 'success') {
			// rerun all `load` functions, following the successful update
			await invalidateAll();
		}

		applyAction(result);
	}
</script>

<form method="POST" on:submit|preventDefault={handleSubmit}>
	<!-- content -->
</form>

処理を進める前に、$app/formsdeserialize でレスポンスをデシリアライズする必要があることにご注意ください。JSON.parse() では不十分です。なぜなら、例えば load 関数のような form action は、DateBigInt オブジェクトも戻り値としてサポートしているからです。

もし +page.server.js+server.js のどちらも存在する場合、デフォルトでは、fetch リクエストは +server.js のほうにルーティングされます。+page.server.js の action に POST をするには、カスタムの x-sveltekit-action ヘッダーを使用します:

const const response: Responseresponse = await function fetch(input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response> (+1 overload)fetch(this.action, {
	RequestInit.method?: string | undefined

A string to set request’s method.

method
: 'POST',
RequestInit.body?: BodyInit | null | undefined

A BodyInit object or null to set request’s body.

body
: data,
RequestInit.headers?: HeadersInit | undefined

A Headers object, an object literal, or an array of two-item arrays to set request’s headers.

headers
: {
'x-sveltekit-action': 'true' } });

Alternatives

サーバーにデータを送信する方法として、プログレッシブな強化(progressively enhance)を行うことができるため Form actions は望ましい方法ですが、+server.js ファイルを使用して (例えば) JSON API を公開することもできます。それは例えばこのように行います:

src/routes/send-message/+page
<script>
	function rerun() {
		fetch('/api/ci', {
			method: 'POST'
		});
	}
</script>

<button on:click={rerun}>Rerun CI</button>
src/routes/api/ci/+server
/** @type {import('./$types').RequestHandler} */
export function function POST(): void
@type{import('./$types').RequestHandler}
POST
() {
// do something }
import type { 
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
RequestHandler
} from './$types';
export const const POST: RequestHandlerPOST:
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
type RequestHandler = (event: Kit.RequestEvent<Record<string, any>, string | null>) => MaybePromise<Response>
RequestHandler
= () => {
// do something };

GET vs POST

これまで見てきたように、フォームアクションを使うには、method="POST" を使用する必要があります。

サーバーにデータを POST する必要がないフォームもあるでしょう — 例えば検索入力(search inputs)です。これに対応するには method="GET" (または、method を全く書かないのも同等です) を使うことができ、そして SvelteKit はそれを <a> 要素のように扱い、フルページナビゲーションの代わりにクライアントサイドルーターを使用します。:

<form action="/search">
	<label>
		Search
		<input name="q">
	</label>
</form>

この form を送信すると /search?q=... に移動して load 関数が実行されますが、action は実行されません。<a> 要素と同じように、data-sveltekit-reload 属性、 data-sveltekit-replacestate 属性、data-sveltekit-keepfocus 属性、 data-sveltekit-noscroll 属性を <form> に設定することができ、ルーターの挙動をコントロールすることができます。

その他の参考資料

Edit this page on GitHub