Now one thing that you've learned very quickly as a web
developer is that you cannot trust users, they will cause chaos given the chance.
And we need to make sure that they're not gonna submit gibberish
data using our phones.
The first line of defense is the browser's built in validation,
which makes it easy to for example, mark the input as required.
So let's go to the add to-do input.
I'm just gonna add the required attribute.
And now if you're try and submit a to-do without any data,
we'll see a notification from the browser saying, please fill out this field.
This kind of validation, is helpful, and you absolutely should add it,
gives you a nice user interface for free, but it's also insufficient.
There are some validation rules that can't be encoded using these attributes,
for example, you might have a uniqueness requirement.
In any case, if the user knows how to use DevTools, then they might just go in and
get rid of the required attribute or something like that.
So to guard against people doing malicious things like that,
you should always use set aside validation,
as well as client side validation.
If you have a choice,
do the set aside validation first.
So all right, and in the database JS file
we're gonna do the validation when someone calls createTodo.
First thing we'll do is if description is empty.
We'll throw an error.
And the error is gonna be todo must have a description.
And then we're gonna get the user's existing todos so
that we can do a uniqueness check.
If todos.find(todo), Todo.description,
Is equal the description that we've just submitted, well,
then we're gonna throw an error that says todos must be unique.
Right, and so now if we submit a duplicate todo, We get an error page.
It's probably not exactly what we want, but it's a good start.
It would be nice if we could stay on the same page where the form was submitted and
give the user an opportunity to correct them, their mistake.
So inside our page server JS file,
we're gonna import a new module, fail from SvelteKit.
And inside our create action, once we got the data,
we're gonna try to create the Todo.
And if it fails, we catch the error.
And we're gonna return a fail object.
Given an HTTP code of 422,
which indicates that there was something wrong with the data that was submitted.
We'll pass the description back to the page so that we can render it in the UI.
We don't just pass all of the data that the user submitted back automatically,
because they could include things like passwords and
credit card data that we wanna be careful about where we put that.
And finally, the error property of this fail object is gonna be
the message that was thrown from the Create todo function.
You have a question from the internet?
>> What's the difference between the fail and error helpers from SveltKit?
>> Yep, so we're gonna get into the weeds of error handling later on.
But essentially if you just throw new error with some message,
then Svelte is gonna throw his hands up say, I don't know what to do with this.
I'm just gonna render an error page and
I'm gonna tell the user that an internal error happened.
If you throw an error that was created with the error helper from SvelteKit,
then SvelteKit is like, okay, the user, the developer knows
what they're doing, this is an error that they expected.
And so will actually display the message of that error to the user instead of
a generic internal error.
When you're submitting form data, this isn't an application error.
If the data is wrong, it's a validation error.
And we wanna be able to distinguish between errors that should result in
the error page being shown and errors that should be sent back to the user, so
that it can be incorporated into the UI without showing an error page.
And that's where this fail helper comes in.
So an action can return data, which is made available to the page.
And by wrapping it in this fail function,
we're telling SvelteKit that the user submitted incorrect data.
And that's useful for displaying the correct status code and things like that.
Okay, so in our page.svelte, we can now access the data that was returned
from the action via the form prop, which sits alongside export lead data.
So let's create that export lead form.
And below the h1 we'll add an F blog.
If form question mark dot error, the question mark is there because if we're
on this page and we haven't just submitted some data form won't exist.
But if the form object does exist and it contains an error property,
then we know that we need to render some error UI.
P class equals error and then we're
just gonna display form.error to the user.
And finally, we're gonna add the value that was previously submitted in
the description to the input so that the user doesn't have to retype it.
So if the form exists, we'll grab the description.
If it doesn't, then we'll default to the empty string.
Okay, so this time, if we do the same thing, we try and
submit a duplicate todo, Learn SvelteKit.
Well, that's embarrassing.
I must have missed a part here.
I must have missed a bar here, I'm gonna open the terminal, see what happened.
Okay, data.get is not a function.
So, there's an error in my code.
We'll go to page server.js and see where that's happening.
Is because you'll notice up here this data object,
I called await request form data, but I forgot to add the parentheses somehow.
So, I'll fix that.
And now, when I add the duplicate todo,
It's gonna display the error that was thrown from the create todo function.