Movatterモバイル変換


[0]ホーム

URL:


Skip to main content
SvelteKitCore concepts

Form actions

A+page.server.js file can exportactions, which allow you toPOST data to the server using the<form> element.

When using<form>, client-side JavaScript is optional, but you can easilyprogressively enhance your form interactions with JavaScript to provide the best user experience.

Default actions

In the simplest case, a page declares adefault action:

src/routes/login/+page.server
/**@satisfies{import('./$types').Actions}*/exportconst
constactions:{default:(event:any)=>Promise<void>;}
@satisfies{import('./$types').Actions}
actions
={
default: (event:any)=>Promise<void>default:async(event:anyevent)=>{// TODO log the user in}};
importtype{
typeActions={[x:string]:Kit.Action<Record<string,any>,void|Record<string,any>,string|null>;}typeActions={[x:string]:Kit.Action<Record<string,any>,void|Record<string,any>,string|null>;}
Actions
}from'./$types';
exportconst
constactions:{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
typeActions={[x:string]:Kit.Action<Record<string,any>,void|Record<string,any>,string|null>;}typeActions={[x:string]:Kit.Action<Record<string,any>,void|Record<string,any>,string|null>;}
Actions
;

To invoke this action from the/login page, just add a<form> — no JavaScript needed:

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

If someone were to click the button, the browser would send the form data viaPOST request to the server, running the default action.

Actions always usePOST requests, sinceGET requests should never have side-effects.

We can also invoke the action from other pages (for example if there’s a login widget in the nav in the root layout) by adding theaction attribute, pointing to the page:

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

Named actions

Instead of onedefault action, a page can have as many named actions as it needs:

src/routes/login/+page.server
/**@satisfies{import('./$types').Actions}*/exportconst
constactions:{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}};
importtype{
typeActions={[x:string]:Kit.Action<Record<string,any>,void|Record<string,any>,string|null>;}typeActions={[x:string]:Kit.Action<Record<string,any>,void|Record<string,any>,string|null>;}
Actions
}from'./$types';
exportconst
constactions:{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
typeActions={[x:string]:Kit.Action<Record<string,any>,void|Record<string,any>,string|null>;}typeActions={[x:string]:Kit.Action<Record<string,any>,void|Record<string,any>,string|null>;}
Actions
;

To invoke a named action, add a query parameter with the name prefixed by a/ character:

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

As well as theaction attribute, we can use theformaction attribute on a button toPOST the same form data to a different action than the parent<form>:

src/routes/login/+page
<formmethod="POST"action="?/login"><label>Email<inputname="email"type="email"></label><label>Password<inputname="password"type="password"></label><button>Log in</button><buttonformaction="?/register">Register</button></form>

We can’t have default actions next to named actions, because if you POST to a named action without a redirect, the query parameter is persisted in the URL, which means the next default POST would go through the named action from before.

Anatomy of an action

Each action receives aRequestEvent object, allowing you to read the data withrequest.formData(). After processing the request (for example, logging the user in by setting a cookie), the action can respond with data that will be available through theform property on the corresponding page and throughpage.form app-wide until the next update.

src/routes/login/+page.server
import*asmodule"$lib/server/db"dbfrom'$lib/server/db';/**@type{import('./$types').PageServerLoad}*/exportasyncfunctionfunctionload(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
}) {
constconstuser:anyuser=awaitmodule"$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 withcookies.set, or from the request headers.

@paramname the name of the cookie
@paramopts the options, passed directly tocookie.parse. See documentationhere
get
('sessionid'));
return{user:anyuser};}/**@satisfies{import('./$types').Actions}*/exportconst
constactions:{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
})=>{
constconstdata:FormDatadata=awaitrequest:Request

The original request object.

request
.Body.formData():Promise<FormData>formData();
constconstemail:FormDataEntryValue|nullemail=constdata:FormDatadata.FormData.get(name: string): FormDataEntryValue|nullget('email');constconstpassword:FormDataEntryValue|nullpassword=constdata:FormDatadata.FormData.get(name: string): FormDataEntryValue|nullget('password');constconstuser:anyuser=awaitmodule"$lib/server/db"db.getUser(constemail: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 aset-cookie header to the response, but also make the cookie available viacookies.get orcookies.getAll during the current request.

ThehttpOnly andsecure options aretrue by default (except onhttp://localhost, wheresecure isfalse), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. ThesameSite option defaults tolax.

You must specify apath for the cookie. In most cases you should explicitly setpath: '/' to make the cookie available throughout your app. You can use relative paths, or setpath: '' 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 tocookie.serialize. See documentationhere
set
('sessionid',awaitmodule"$lib/server/db"db.createSession(constuser:anyuser),{path:string

Specifies the value for the {@linkhttps://tools.ietf.org/html/rfc6265#section-5.2.4PathSet-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*asmodule"$lib/server/db"dbfrom'$lib/server/db';importtype{typePageServerLoad=(event:ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>PageServerLoad,
typeActions={[x:string]:Action<Record<string,any>,void|Record<string,any>,string|null>;}
Actions
}from'./$types';
exportconstconstload:PageServerLoadload:typePageServerLoad=(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
})=>{
constconstuser:anyuser=awaitmodule"$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 withcookies.set, or from the request headers.

@paramname the name of the cookie
@paramopts the options, passed directly tocookie.parse. See documentationhere
get
('sessionid'));
return{user:anyuser};};exportconst
constactions:{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
})=>{
constconstdata:FormDatadata=awaitrequest:Request

The original request object.

request
.Body.formData():Promise<FormData>formData();
constconstemail:FormDataEntryValue|nullemail=constdata:FormDatadata.FormData.get(name: string): FormDataEntryValue|nullget('email');constconstpassword:FormDataEntryValue|nullpassword=constdata:FormDatadata.FormData.get(name: string): FormDataEntryValue|nullget('password');constconstuser:anyuser=awaitmodule"$lib/server/db"db.getUser(constemail: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 aset-cookie header to the response, but also make the cookie available viacookies.get orcookies.getAll during the current request.

ThehttpOnly andsecure options aretrue by default (except onhttp://localhost, wheresecure isfalse), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. ThesameSite option defaults tolax.

You must specify apath for the cookie. In most cases you should explicitly setpath: '/' to make the cookie available throughout your app. You can use relative paths, or setpath: '' 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 tocookie.serialize. See documentationhere
set
('sessionid',awaitmodule"$lib/server/db"db.createSession(constuser:anyuser),{path:string

Specifies the value for the {@linkhttps://tools.ietf.org/html/rfc6265#section-5.2.4PathSet-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
typeActions={[x:string]:Action<Record<string,any>,void|Record<string,any>,string|null>;}
Actions
;
src/routes/login/+page
<script>/**@type{import('./$types').PageProps}*/let{ data,form }=$props();</script>{#ifform?.success}<!-- this message is ephemeral; it exists because the page was rendered inresponse to a form submission. it will vanish if the user reloads --><p>Successfully logged in! Welcome back, {data.user.name}</p>{/if}
<scriptlang="ts">importtype{ PageProps }from'./$types';let{ data,form }:PageProps=$props();</script>{#ifform?.success}<!-- this message is ephemeral; it exists because the page was rendered inresponse to a form submission. it will vanish if the user reloads --><p>Successfully logged in! Welcome back, {data.user.name}</p>{/if}
Legacy mode

PageProps was added in 2.16.0. In earlier versions, you had to type thedata andform properties individually:

+page
/**@type{{ data: import('./$types').PageData, form: import('./$types').ActionData }}*/let{letdata:anydata,letform:anyform}=
function$props():anynamespace$props

Declares the props that a component accepts. Example:

let{ optionalProp=42,requiredProp,bindableProp=$bindable() }:{ optionalProp?:number; requiredProps:string; bindableProp:boolean}=$props();

https://svelte.dev/docs/svelte/$props

$props
();
importtype{importPageDataPageData,importActionDataActionData}from'./$types';let{letdata:PageDatadata,letform:ActionDataform}:{data:PageDatadata:importPageDataPageData,form:ActionDataform:importActionDataActionData}=
function$props():anynamespace$props

Declares the props that a component accepts. Example:

let{ optionalProp=42,requiredProp,bindableProp=$bindable() }:{ optionalProp?:number; requiredProps:string; bindableProp:boolean}=$props();

https://svelte.dev/docs/svelte/$props

$props
();

In Svelte 4, you’d useexport let data andexport let form instead to declare properties.

Validation errors

If the request couldn’t be processed because of invalid data, you can return validation errors — along with the previously submitted form values — back to the user so that they can try again. Thefail function lets you return an HTTP status code (typically 400 or 422, in the case of validation errors) along with the data. The status code is available throughpage.status and the data throughform:

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

Create anActionFailure object. Call when form submission fails.

@paramstatus TheHTTP status code. Must be in the range 400-599.
fail
}from'@sveltejs/kit';
import*asmodule"$lib/server/db"dbfrom'$lib/server/db';/**@satisfies{import('./$types').Actions}*/exportconst
constactions:{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
})=>{
constconstdata:FormDatadata=awaitrequest:Request

The original request object.

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

Create anActionFailure object. Call when form submission fails.

@paramstatus TheHTTP 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});
}constconstuser:anyuser=awaitmodule"$lib/server/db"db.getUser(constemail:FormDataEntryValueemail);if(!constuser:anyuser||constuser:anyuser.password!==module"$lib/server/db"db.hash(constpassword:FormDataEntryValue|nullpassword)) {return
fail<{email:FormDataEntryValue;incorrect:boolean;}>(status:number,data:{email:FormDataEntryValue;incorrect:boolean;}):ActionFailure<{email:FormDataEntryValue;incorrect:boolean;}> (+1overload)

Create anActionFailure object. Call when form submission fails.

@paramstatus TheHTTP 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 aset-cookie header to the response, but also make the cookie available viacookies.get orcookies.getAll during the current request.

ThehttpOnly andsecure options aretrue by default (except onhttp://localhost, wheresecure isfalse), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. ThesameSite option defaults tolax.

You must specify apath for the cookie. In most cases you should explicitly setpath: '/' to make the cookie available throughout your app. You can use relative paths, or setpath: '' 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 tocookie.serialize. See documentationhere
set
('sessionid',awaitmodule"$lib/server/db"db.createSession(constuser:anyuser),{path:string

Specifies the value for the {@linkhttps://tools.ietf.org/html/rfc6265#section-5.2.4PathSet-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{functionfail(status:number):ActionFailure<undefined> (+1overload)

Create anActionFailure object. Call when form submission fails.

@paramstatus TheHTTP status code. Must be in the range 400-599.
fail
}from'@sveltejs/kit';
import*asmodule"$lib/server/db"dbfrom'$lib/server/db';importtype{
typeActions={[x:string]:Action<Record<string,any>,void|Record<string,any>,string|null>;}
Actions
}from'./$types';
exportconst
constactions:{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
})=>{
constconstdata:FormDatadata=awaitrequest:Request

The original request object.

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

Create anActionFailure object. Call when form submission fails.

@paramstatus TheHTTP 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});
}constconstuser:anyuser=awaitmodule"$lib/server/db"db.getUser(constemail:FormDataEntryValueemail);if(!constuser:anyuser||constuser:anyuser.password!==module"$lib/server/db"db.hash(constpassword:FormDataEntryValue|nullpassword)) {return
fail<{email:FormDataEntryValue;incorrect:boolean;}>(status:number,data:{email:FormDataEntryValue;incorrect:boolean;}):ActionFailure<{email:FormDataEntryValue;incorrect:boolean;}> (+1overload)

Create anActionFailure object. Call when form submission fails.

@paramstatus TheHTTP 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 aset-cookie header to the response, but also make the cookie available viacookies.get orcookies.getAll during the current request.

ThehttpOnly andsecure options aretrue by default (except onhttp://localhost, wheresecure isfalse), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. ThesameSite option defaults tolax.

You must specify apath for the cookie. In most cases you should explicitly setpath: '/' to make the cookie available throughout your app. You can use relative paths, or setpath: '' 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 tocookie.serialize. See documentationhere
set
('sessionid',awaitmodule"$lib/server/db"db.createSession(constuser:anyuser),{path:string

Specifies the value for the {@linkhttps://tools.ietf.org/html/rfc6265#section-5.2.4PathSet-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
typeActions={[x:string]:Action<Record<string,any>,void|Record<string,any>,string|null>;}
Actions
;

Note that as a precaution, we only return the email back to the page — not the password.

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

The returned data must be serializable as JSON. Beyond that, the structure is entirely up to you. For example, if you had multiple forms on the page, you could distinguish which<form> the returnedform data referred to with anid property or similar.

Redirects

Redirects (and errors) work exactly the same as inload:

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

Create anActionFailure object. Call when form submission fails.

@paramstatus TheHTTP status code. Must be in the range 400-599.
fail
,functionredirect(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.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)
  • 307 Temporary Redirect: redirect will keep the request method
  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus TheHTTP 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*asmodule"$lib/server/db"dbfrom'$lib/server/db';/**@satisfies{import('./$types').Actions}*/exportconst
constactions:{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
})=>{
constconstdata:FormDatadata=awaitrequest:Request

The original request object.

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

Create anActionFailure object. Call when form submission fails.

@paramstatus TheHTTP 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(constuser:anyuser.password!==module"$lib/server/db"db.hash(constpassword:FormDataEntryValue|nullpassword)) {return
fail<{email:FormDataEntryValue|null;incorrect:boolean;}>(status:number,data:{email:FormDataEntryValue|null;incorrect:boolean;}):ActionFailure<...> (+1overload)

Create anActionFailure object. Call when form submission fails.

@paramstatus TheHTTP 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 aset-cookie header to the response, but also make the cookie available viacookies.get orcookies.getAll during the current request.

ThehttpOnly andsecure options aretrue by default (except onhttp://localhost, wheresecure isfalse), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. ThesameSite option defaults tolax.

You must specify apath for the cookie. In most cases you should explicitly setpath: '/' to make the cookie available throughout your app. You can use relative paths, or setpath: '' 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 tocookie.serialize. See documentationhere
set
('sessionid',awaitmodule"$lib/server/db"db.createSession(constuser:anyuser),{path:string

Specifies the value for the {@linkhttps://tools.ietf.org/html/rfc6265#section-5.2.4PathSet-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')) {
functionredirect(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.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)
  • 307 Temporary Redirect: redirect will keep the request method
  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus TheHTTP 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}};
import{functionfail(status:number):ActionFailure<undefined> (+1overload)

Create anActionFailure object. Call when form submission fails.

@paramstatus TheHTTP status code. Must be in the range 400-599.
fail
,functionredirect(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.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)
  • 307 Temporary Redirect: redirect will keep the request method
  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus TheHTTP 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*asmodule"$lib/server/db"dbfrom'$lib/server/db';importtype{
typeActions={[x:string]:Action<Record<string,any>,void|Record<string,any>,string|null>;}
Actions
}from'./$types';
exportconst
constactions:{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
})=>{
constconstdata:FormDatadata=awaitrequest:Request

The original request object.

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

Create anActionFailure object. Call when form submission fails.

@paramstatus TheHTTP 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(constuser:anyuser.password!==module"$lib/server/db"db.hash(constpassword:FormDataEntryValue|nullpassword)) {return
fail<{email:FormDataEntryValue|null;incorrect:boolean;}>(status:number,data:{email:FormDataEntryValue|null;incorrect:boolean;}):ActionFailure<...> (+1overload)

Create anActionFailure object. Call when form submission fails.

@paramstatus TheHTTP 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 aset-cookie header to the response, but also make the cookie available viacookies.get orcookies.getAll during the current request.

ThehttpOnly andsecure options aretrue by default (except onhttp://localhost, wheresecure isfalse), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. ThesameSite option defaults tolax.

You must specify apath for the cookie. In most cases you should explicitly setpath: '/' to make the cookie available throughout your app. You can use relative paths, or setpath: '' 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 tocookie.serialize. See documentationhere
set
('sessionid',awaitmodule"$lib/server/db"db.createSession(constuser:anyuser),{path:string

Specifies the value for the {@linkhttps://tools.ietf.org/html/rfc6265#section-5.2.4PathSet-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')) {
functionredirect(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.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)
  • 307 Temporary Redirect: redirect will keep the request method
  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus TheHTTP 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
typeActions={[x:string]:Action<Record<string,any>,void|Record<string,any>,string|null>;}
Actions
;

Loading data

After an action runs, the page will be re-rendered (unless a redirect or an unexpected error occurs), with the action’s return value available to the page as theform prop. This means that your page’sload functions will run after the action completes.

Note thathandle runs before the action is invoked, and does not rerun before theload functions. This means that if, for example, you usehandle to populateevent.locals based on a cookie, you must updateevent.locals when you set or delete the cookie in an action:

src/hooks.server
/**@type{import('@sveltejs/kit').Handle}*/exportasyncfunction
functionhandle(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 theserver handle hook.

locals
.
App.Locals.user: {name:string;}|null
user
=await
functiongetUser(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 withcookies.set, or from the request headers.

@paramname the name of the cookie
@paramopts the options, passed directly tocookie.parse. See documentationhere
get
('sessionid'));
returnresolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>resolve(event:RequestEvent<Partial<Record<string,string>>,string|null>event);}
importtype{
typeHandle=(input:{event:RequestEvent;resolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>;})=>MaybePromise<...>

Thehandle hook runs every time the SvelteKit server receives arequest anddetermines theresponse.It receives anevent object representing the request and a function calledresolve, which renders the route and generates aResponse.This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).

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

Thehandle hook runs every time the SvelteKit server receives arequest anddetermines theresponse.It receives anevent object representing the request and a function calledresolve, which renders the route and generates aResponse.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 theserver handle hook.

locals
.
App.Locals.user: {name:string;}|null
user
=await
functiongetUser(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 withcookies.set, or from the request headers.

@paramname the name of the cookie
@paramopts the options, passed directly tocookie.parse. See documentationhere
get
('sessionid'));
returnresolve:(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}*/exportfunctionfunctionload(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 theserver handle hook.

locals
.
App.Locals.user: {name:string;}|null
user
};}/**@satisfies{import('./$types').Actions}*/exportconst
constactions:{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 apath for the cookie. In most cases you should explicitly setpath: '/' to make the cookie available throughout your app. You can use relative paths, or setpath: '' to make the cookie only available on the current path and its children

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

Specifies the value for the {@linkhttps://tools.ietf.org/html/rfc6265#section-5.2.4PathSet-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 theserver handle hook.

locals
.
App.Locals.user: {name:string;}|null
user
=null;
}};
importtype{typePageServerLoad=(event:ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>PageServerLoad,
typeActions={[x:string]:Action<Record<string,any>,void|Record<string,any>,string|null>;}
Actions
}from'./$types';
exportconstconstload:PageServerLoadload:typePageServerLoad=(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 theserver handle hook.

locals
.
App.Locals.user: {name:string;}|null
user
};};exportconst
constactions:{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 apath for the cookie. In most cases you should explicitly setpath: '/' to make the cookie available throughout your app. You can use relative paths, or setpath: '' to make the cookie only available on the current path and its children

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

Specifies the value for the {@linkhttps://tools.ietf.org/html/rfc6265#section-5.2.4PathSet-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 theserver handle hook.

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

Progressive enhancement

In the preceding sections we built a/login action thatworks without client-side JavaScript — not afetch in sight. That’s great, but when JavaScriptis available we can progressively enhance our form interactions to provide a better user experience.

use:enhance

The easiest way to progressively enhance a form is to add theuse:enhance action:

src/routes/login/+page
<script>import{ enhance }from'$app/forms';/**@type{import('./$types').PageProps}*/let{ form }=$props();</script><formmethod="POST"use:enhance>
<scriptlang="ts">import{ enhance }from'$app/forms';importtype{ PageProps }from'./$types';let{ form }:PageProps=$props();</script><formmethod="POST"use:enhance>

use:enhance can only be used with forms that havemethod="POST" and point to actions defined in a+page.server.js file. It will not work withmethod="GET", which is the default for forms without a specified method. Attempting to useuse:enhance on forms withoutmethod="POST" or posting to a+server.js endpoint will result in an error.

Yes, it’s a little confusing that theenhance action and<form action> are both called ‘action’. These docs are action-packed. Sorry.

Without an argument,use:enhance will emulate the browser-native behaviour, just without the full-page reloads. It will:

  • update theform property,page.form andpage.status on a successful or invalid response, but only if the action is on the same page you’re submitting from. For example, if your form looks like<form action="/somewhere/else" ..>, theform prop and thepage.form state willnot be updated. This is because in the native form submission case you would be redirected to the page the action is on. If you want to have them updated either way, useapplyAction
  • reset the<form> element
  • invalidate all data usinginvalidateAll on a successful response
  • callgoto on a redirect response
  • render the nearest+error boundary if an error occurs
  • reset focus to the appropriate element

Customising use:enhance

To customise the behaviour, you can provide aSubmitFunction that runs immediately before the form is submitted, and (optionally) returns a callback that runs with theActionResult.

<formmethod="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 submittedreturnasync({ 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};}}>

You can use these functions to show and hide loading UI, and so on.

If you return a callback, you override the default post-submission behavior. To get it back, callupdate, which acceptsinvalidateAll andreset parameters, or useapplyAction on the result:

src/routes/login/+page
<script>import{ enhance,applyAction }from'$app/forms';/**@type{import('./$types').PageProps}*/let{ form }=$props();</script><formmethod="POST"use:enhance={({ formElement,formData,action,cancel })=>{returnasync({ result })=>{// `result` is an `ActionResult` objectif(result.type==='redirect') {goto(result.location);}else{awaitapplyAction(result);}};}}>
<scriptlang="ts">import{ enhance,applyAction }from'$app/forms';importtype{ PageProps }from'./$types';let{ form }:PageProps=$props();</script><formmethod="POST"use:enhance={({ formElement,formData,action,cancel })=>{returnasync({ result })=>{// `result` is an `ActionResult` objectif(result.type==='redirect') {goto(result.location);}else{awaitapplyAction(result);}};}}>

The behaviour ofapplyAction(result) depends onresult.type:

  • success,failure — setspage.status toresult.status and updatesform andpage.form toresult.data (regardless of where you are submitting from, in contrast toupdate fromenhance)
  • redirect — callsgoto(result.location, { invalidateAll: true })
  • error — renders the nearest+error boundary withresult.error

In all cases,focus will be reset.

Custom event listener

We can also implement progressive enhancement ourselves, withoutuse:enhance, with a normal event listener on the<form>:

src/routes/login/+page
<script>import{ invalidateAll,goto }from'$app/navigation';import{ applyAction,deserialize }from'$app/forms';/**@type{import('./$types').PageProps}*/let{ form }=$props();/**@param{SubmitEvent & { currentTarget: EventTarget & HTMLFormElement}}event */asyncfunctionhandleSubmit(event) {event.preventDefault();constdata=newFormData(event.currentTarget);constresponse=awaitfetch(event.currentTarget.action,{method:'POST',body:data});/**@type{import('@sveltejs/kit').ActionResult}*/constresult=deserialize(awaitresponse.text());if(result.type==='success') {// rerun all `load` functions, following the successful updateawaitinvalidateAll();}applyAction(result);}</script><formmethod="POST"onsubmit={handleSubmit}><!-- content --></form>
<scriptlang="ts">import{ invalidateAll,goto }from'$app/navigation';import{ applyAction,deserialize }from'$app/forms';importtype{ PageProps }from'./$types';importtype{ ActionResult }from'@sveltejs/kit';let{ form }:PageProps=$props();asyncfunctionhandleSubmit(event:SubmitEvent&{ currentTarget:EventTarget&HTMLFormElement}) {event.preventDefault();constdata=newFormData(event.currentTarget);constresponse=awaitfetch(event.currentTarget.action,{method:'POST',body:data});constresult:ActionResult=deserialize(awaitresponse.text());if(result.type==='success') {// rerun all `load` functions, following the successful updateawaitinvalidateAll();}applyAction(result);}</script><formmethod="POST"onsubmit={handleSubmit}><!-- content --></form>

Note that you need todeserialize the response before processing it further using the corresponding method from$app/forms.JSON.parse() isn’t enough because form actions - likeload functions - also support returningDate orBigInt objects.

If you have a+server.js alongside your+page.server.js,fetch requests will be routed there by default. ToPOST to an action in+page.server.js instead, use the customx-sveltekit-action header:

constconstresponse:Responseresponse=awaitfunctionfetch(input:string|URL|globalThis.Request,init?:RequestInit):Promise<Response> (+1overload)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

Form actions are the preferred way to send data to the server, since they can be progressively enhanced, but you can also use+server.js files to expose (for example) a JSON API. Here’s how such an interaction could look like:

src/routes/send-message/+page
<script>functionrerun() {fetch('/api/ci',{method:'POST'});}</script><buttononclick={rerun}>Rerun CI</button>
<scriptlang="ts">functionrerun() {fetch('/api/ci',{method:'POST'});}</script><buttononclick={rerun}>Rerun CI</button>
src/routes/api/ci/+server
/**@type{import('./$types').RequestHandler}*/exportfunctionfunctionPOST():void
@type{import('./$types').RequestHandler}
POST
() {
// do something}
importtype{
typeRequestHandler=(event:Kit.RequestEvent<Record<string,any>,string|null>)=>MaybePromise<Response>typeRequestHandler=(event:Kit.RequestEvent<Record<string,any>,string|null>)=>MaybePromise<Response>
RequestHandler
}from'./$types';
exportconstconstPOST:RequestHandlerPOST:
typeRequestHandler=(event:Kit.RequestEvent<Record<string,any>,string|null>)=>MaybePromise<Response>typeRequestHandler=(event:Kit.RequestEvent<Record<string,any>,string|null>)=>MaybePromise<Response>
RequestHandler
=()=>{
// do something};

GET vs POST

As we’ve seen, to invoke a form action you must usemethod="POST".

Some forms don’t need toPOST data to the server — search inputs, for example. For these you can usemethod="GET" (or, equivalently, nomethod at all), and SvelteKit will treat them like<a> elements, using the client-side router instead of a full page navigation:

<formaction="/search"><label>Search<inputname="q"></label></form>

Submitting this form will navigate to/search?q=... and invoke your load function but will not invoke an action. As with<a> elements, you can set thedata-sveltekit-reload,data-sveltekit-replacestate,data-sveltekit-keepfocus anddata-sveltekit-noscroll attributes on the<form> to control the router’s behaviour.

Further reading

Edit this page on GitHub llms.txt


[8]ページ先頭

©2009-2025 Movatter.jp