Okay, let's talk about forms, one of my favorite topics.
So in the chat on loading, we saw how to get data from the server to the browser,
but sometimes you need to send data in the opposite direction.
You need to get data from the browser back to the server, and that's where the form
element, which is the web platform's way of submitting data comes into play.
So let's build a little todo app.
We've already got an in memory database setup in this lips of a database module,
and we're just putting everything in a map.
Obviously in a real app, you would use an actual database but
we're not gonna do that for this tutorial.
And we have a load function in source/routes/page.server.js,
that uses the cookies API to get ahold of the current user ID,
if the user doesn't yet have an ID, it assigns one.
It gets the todos that belong to that user.
So this allows us to have a per-user todo list, but we need to add a form so
that we can create new todos.
So go over to src/route/page.svelte, and below the H1, we're gonna add
a form element With a method of post, cuz we're gonna post some data to the server.
Inside there, we'll create a label,
Add some text, add a todo, Then we'll create an input.
Give it a name which is gonna be description.
And I'm gonna disable autocomplete as well.
So we can now type into this form and submit some data, but we get a 405 error
because no actions exist for this page right now so we can fix that.
What we need to do is create an action in our page.server.js file.
This is the counterpart to the load function.
So down here, create an actions object.
And we're gonna create a default action, Which is gonna be an async function.
That's gonna grab the cookies and the request object.
And first of all,
is gonna grab the description from that input by requesting the form data
And getting the description.
And it's gonna create it todo in the mat that belongs to the current user.
So db.createTodo(cookies.get(userid)
data.get Description.
Okay, this request object here,
this is a standard request interface that is part of the web platform.
You can learn about the request object on MDN if you're not familiar,
it's something that you'll use a lot in web development.
And SvelteKit uses standard web APIs as far as it can.
When we call await request.formData, that returns an instance of the FormData API,
which is the same object that you get in the browser if you call new FormData,
and then pass in a form element.
So now if we type in some data, And hit Enter,
post it to the server, you'll see that it reloads the page with the new data.
And you'll notice that we haven't had to add any fetch code,
we haven't had to do error handling and stuff like that.
Data updates automatically.
And because we're using a form element,
this app would continue to work even if JavaScript was disabled.
And we can actually demonstrate that by opening this app in a new tab.
I'm gonna open the settings.
Scroll down to Disable JavaScript, reload the page.
Hit Enter, and the page reloads even though we're not using JavaScript, we
see up to date personalized data and close that window now get back to the tutorial.
So just now we use a default action but in practice,
a page that only has a single action is actually quite rare.
Most of the time you will need to have multiple actions on a page.
So in the case of our todo app,
we wanna be able to delete todos once we've completed them.
First thing we're gonna do is get rid of the default action and
turn it into a named action, call it create.
And then we'll create a new one, let's call it delete.
And it's gonna be the same deal.
It's an async function, uses cookies and request.
We're gonna get the data, And we're gonna delete the todo.
This time the data that we're gonna get from the form is an ID property.
Now the first thing we wanna do before we implement the delete action inside our
page is we need to update the form action that creates the todo.
So go back to page.svelte, scroll up to the form, and
we're gonna add an action attribute.
By default, the action is the same as the current page.
And so if you just have form method equals post without specifying an action,
that is gonna call the default action on the page that you're currently on.
But in this case, we wanna use a named action.
We'll do that by adding a query parameter with a value of
create with a slash in front of it.
So what this means is we take the current URL and we append a query string
with a parameter whose name is /create and which doesn't have a value.
And that tells SvelteKit that we're trying to invoke the create action on this page.
Now the action doesn't have to be on this page, you can actually have an action that
points to a different page entirely, which is very useful when you're building things
like login and logout forms that should exist on all pages of your app.
Okay, so lastly, we wanna create a form for each of the todos in our list.
So inside here, instead of just having that description,
lead form method = POST, Invoke the delete action.
And you'll recall that inside the action,
we were referring to an ID property that we need to make available.
So each todo has an ID already.
And to add that to the form without showing it to the user,
because the user doesn't want a random string of digits,
we'll do input type = hidden, give it a name of id so
that we can get it with form.getid, and
the value is gonna be todo.id.
Let a span containing the todo description.
And then we're gonna add a button with a label So
that people who can't see the icon that is about to appear
can also understand what this button is going to do.
Okay, you'll see that we have these little trash can icons down here
that's coming from the remove.svg which is being controlled down here with some CSS.
So if we've wired everything up correctly,
then we should now be able to delete todos as well as add them.
And indeed it works.
And so if we refresh the page, we'll see that those todos stay deleted.