メインコンテンツへスキップ

フォームアクション

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

<form> を使用する場合、クライアント側の JavaScript はオプションですが、JavaScript でフォームのインタラクションを簡単に *プログレッシブエンハンスメント* して、最高のユーザーエクスペリエンスを提供できます。

デフォルトアクション

最も簡単なケースでは、ページは default アクションを宣言します。

src/routes/login/+page.server
/** @satisfies {import('./$types').Actions} */
export const 
const actions: {
    default: (event: any) => Promise<void>;
}
@satisfies{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: {
    default: (event: Kit.RequestEvent<Record<string, any>, string | null>) => Promise<void>;
}
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 } } 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
;

/login ページからこのアクションを呼び出すには、<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>

誰かがボタンをクリックすると、ブラウザはフォームデータを POST リクエストでサーバーに送信し、デフォルトアクションを実行します。

GET リクエストには副作用があってはならないため、アクションは常に POST リクエストを使用します。

action 属性を追加して、ページを指すことで、他のページからアクションを呼び出すこともできます(たとえば、ルートレイアウトのナビゲーションにログインウィジェットがある場合)。

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

名前付きアクション

1つの default アクションの代わりに、ページには必要なだけ名前付きアクションを含めることができます。

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
;

名前付きアクションを呼び出すには、名前の前に / 文字が付いたクエリパラメーターを追加します。

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

action 属性に加えて、ボタンで formaction 属性を使用して、親の <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>

名前付きアクションにリダイレクトなしで POST した場合、クエリパラメーターが URL に残ってしまうため、名前付きアクションの横にデフォルトアクションを設定することはできません。つまり、次のデフォルト POST は以前の名前付きアクションを経由することになります。

アクションの構造

各アクションは RequestEvent オブジェクトを受け取り、request.formData() でデータを読み取ることができます。リクエストを処理した後(たとえば、Cookie を設定してユーザーをログインするなど)、アクションは、対応するページの 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}
	<!-- this message is ephemeral; it exists because the page was rendered in
	       response to a form submission. it will vanish if the user reloads -->
	<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}
	<!-- this message is ephemeral; it exists because the page was rendered in
	       response to a form submission. it will vanish if the user reloads -->
	<p>Successfully logged in! Welcome back, {data.user.name}</p>
{/if}
レガシーモード

Svelte 4 では、プロパティを宣言するために、代わりに export let dataexport let form を使用していました。

検証エラー

無効なデータが原因でリクエストを処理できなかった場合、以前に送信されたフォームの値とともに検証エラーをユーザーに返すことができるため、ユーザーは再試行できます。fail 関数を使用すると、(検証エラーの場合は通常 400 または 422 の)HTTP ステータスコードをデータとともに返すことができます。ステータスコードは $page.status で、データは 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
;

念のため、メールアドレスのみをページに返送し、パスワードは返送しないことに注意してください。

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> を参照しているかを、id プロパティなどで区別できます。

リダイレクト

リダイレクト(およびエラー)は、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
;

データの読み込み

アクションの実行後、ページは(リダイレクトまたは予期しないエラーが発生しない限り)再レンダリングされ、アクションの戻り値が form プロップとしてページで利用できるようになります。これは、ページが読み込まれた後、ページ内の load 関数が実行されることを意味します。

handle はアクションが呼び出される前に実行され、load 関数の前に再実行されないことに注意してください。たとえば、handle を使用して Cookie に基づいて event.locals を設定する場合、アクションで 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
;

プログレッシブエンハンスメント

前のセクションでは、クライアント側の JavaScript なしで動作する /login アクションを構築しました。つまり、fetch はどこにもありません。それは素晴らしいことですが、JavaScript が利用可能な場合、フォームのインタラクションをプログレッシブに拡張して、より良いユーザーエクスペリエンスを提供できます。

use:enhance

フォームをプログレッシブに拡張する最も簡単な方法は、use:enhance アクションを追加することです。

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:enhancemethod="POST" を持つフォームでのみ使用できます。指定されたメソッドがないフォームのデフォルトである method="GET" では機能しません。method="POST" を持たないフォームで use:enhance を使用しようとすると、エラーが発生します。

ええ、enhance アクションと <form action> の両方が「action」と呼ばれているのは少し紛らわしいですね。これらのドキュメントはアクション満載です。すみません。

引数なしで、use:enhance はブラウザネイティブの動作をエミュレートします。ただし、ページ全体の再読み込みは行いません。以下を行います。

  • アクションが送信元のページと同じページにある場合にのみ、成功または無効な応答があったときに form プロパティ、$page.form および $page.status を更新します。たとえば、フォームが <form action="/somewhere/else" ..> のようになっている場合、form$page は更新されません。これは、ネイティブフォームの送信ケースでは、アクションがあるページにリダイレクトされるためです。どちらの場合も更新したい場合は、applyAction を使用してください。
  • <form> 要素をリセットします
  • 成功した応答で invalidateAll を使用してすべてのデータを無効にします
  • リダイレクト応答で goto を呼び出します
  • エラーが発生した場合、最も近い +error バウンダリをレンダリングします
  • 適切な要素にフォーカスをリセットします

use:enhance のカスタマイズ

動作をカスタマイズするには、フォームが送信される直前に実行される SubmitFunction を指定し、(オプションで) ActionResult で実行されるコールバックを返すことができます。コールバックを返す場合、上記のデフォルトの動作はトリガーされないことに注意してください。元に戻すには、update を呼び出します。

<form
	method="POST"
	use:enhance={({ formElement, formData, action, cancel, submitter }) => {
		// `formElement` is this `<form>` element
		// `formData` is its `FormData` object that's about to be submitted
		// `action` is the URL to which the form is posted
		// calling `cancel()` will prevent the submission
		// `submitter` is the `HTMLElement` that caused the form to be submitted

		return async ({ result, update }) => {
			// `result` is an `ActionResult` object
			// `update` is a function which triggers the default logic that would be triggered if this callback wasn't set
		};
	}}
>

これらの関数を使用して、読み込み UI などを表示および非表示にできます。

コールバックを返す場合は、デフォルトの use:enhance 動作の一部を再現する必要がある場合がありますが、成功した応答ですべてのデータを無効にする必要はありません。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` is an `ActionResult` object
			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` is an `ActionResult` object
			if (result.type === 'redirect') {
				goto(result.location);
			} else {
				await applyAction(result);
			}
		};
	}}
>

applyAction(result) の動作は result.type によって異なります

  • successfailure$page.statusresult.status に設定し、(enhanceupdate とは対照的に) 送信元に関係なく、form$page.formresult.data に更新します
  • redirectgoto(result.location, { invalidateAll: true }) を呼び出します
  • error — 最も近い +error バウンダリを result.error でレンダリングします

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

カスタムイベントリスナー

use:enhance を使用せずに、<form> の通常のイベントリスナーを使用して、プログレッシブエンハンスメントを自身で実装することもできます。

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" onsubmit|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" onsubmit|preventDefault={handleSubmit}>
	<!-- content -->
</form>

$app/forms の対応する方法を使用して、さらに処理を進める前に応答を deserialize する必要があることに注意してください。フォームアクションは load 関数と同様に、Date または BigInt オブジェクトを返すこともサポートしているため、JSON.parse() だけでは十分ではありません。

+page.server.js とともに +server.js がある場合、fetch リクエストはデフォルトでそこにルーティングされます。代わりに +page.server.js のアクションに 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' } });

代替案

フォームアクションはサーバーにデータを送信するための推奨される方法であり、プログレッシブに拡張できますが、+server.js ファイルを使用して (たとえば) JSON API を公開することもできます。このようなインタラクションは次のようになります。

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

<button onclick={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 する必要はありません。たとえば、検索入力です。これらについては、method="GET" (または、同等の method なし) を使用できます。SvelteKit はそれらを <a> 要素のように扱い、ページ全体のナビゲーションではなくクライアント側のルーターを使用します。

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

このフォームを送信すると、/search?q=... に移動し、ロード関数が呼び出されますが、アクションは呼び出されません。<a> 要素と同様に、ルーターの動作を制御するために、<form>data-sveltekit-reloaddata-sveltekit-replacestatedata-sveltekit-keepfocus および data-sveltekit-noscroll 属性を設定できます。

参考文献

GitHub でこのページを編集する