Forms
For stronger resiliency and user experience, Fresh relies on native browser
support for form submissions with the HTML <form>
element.
In the browser, a <form>
submit will send an HTML action (usually GET
or
POST
) to the server, which responds with a new page to render.
POST request with application/x-www-form-urlencoded
Forms typically submit as a GET
request with data encoded in the URL’s search
parameters, or as a POST
request with either an
application/x-www-form-urlencoded
or multipart/form-data
body.
This example demonstrates how to handle application/x-www-form-urlencoded
<form>
submissions:
import { define } from "../utils.ts";
export const handlers = define.handlers({
async GET(ctx) {
return { data: {} };
},
async POST(ctx) {
const form = await ctx.req.formData();
const email = form.get("email")?.toString();
// Add email to list.
// Redirect user to thank you page.
const headers = new Headers();
headers.set("location", "/thanks-for-subscribing");
return new Response(null, {
status: 303, // See Other
headers,
});
},
});
export default define.page<typeof handlers>(function Subscribe() {
return (
<>
<form method="post">
<input type="email" name="email" value="" />
<button type="submit">Subscribe</button>
</form>
</>
);
});
When the user submits the form, Deno will retrieve the email
value using the
request’s formData()
method, add the email to a list, and redirect the user to
a thank you page.
Handling file uploads
File uploads can be handled in a very similar manner to the example above. Note
that this time, we have to explicitly declare the form’s encoding to be
multipart/form-data
.
import { define } from "../utils.ts";
export const handler = define.handlers({
async GET(ctx) {
return { data: { message: null } };
},
async POST(ctx) {
const form = await ctx.req.formData();
const file = form.get("my-file") as File;
if (!file) {
return { data: { message: "Please try again" } };
}
const name = file.name;
const contents = await file.text();
console.log(contents);
return { data: { message: `${name} uploaded!` } };
},
});
export default define.page<typeof handlers>(function Upload(props) {
const { message } = props.data;
return (
<>
<form method="post" encType="multipart/form-data">
<input type="file" name="my-file" />
<button type="submit">Upload</button>
</form>
{message ? <p>{message}</p> : null}
</>
);
});
A note of caution
These examples are simplified to demonstrate how Deno and Fresh handle HTTP requests. In the Real World™, you’ll want to validate your data (especially the file type) and protect against cross-site request forgery. Consider yourself warned.