SvelteKit Form Validation with Zod

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's going on everyone my name is Hunter and welcome to a brand new spell kit video in today's video we're going to be learning how to implement form validation in spell kit using Zod which is an open source schema validation Library as usual I prepared a good starting point for us which you can find in the starter branch of the repo link below and we just have the markup and styles for a basic registration form that we're gonna be validating it's styled using Daisy UI and Tailwind CSS so with all that out of the way let's go ahead and get started by checking out the Zod documentation so we're going to be using Zod which is a schema declaration and validation library and if we scroll down here a bit we can see how it's actually used you can see that we install it with npm install Zod which if you're using the starter repository then you already have it in your package.json you just need to run npm install and then if we scroll down here a bit we can see that we have a basic usage example and we can see that they start off by importing Z from Zod or Zed however you want to pronounce z and then they Define a schemas they say const my schema equals z dot string so we're creating a schema for Strings and then what we can do is we can run my scheme dot parse and then pass a value into that so in this case they passed in two note this is fine this doesn't error out but since they passed in a number here it throws an error now we're more interested in creating an object schema because our form data is going to be an object so you can see here that they defined a user which is a z dot object and then they're able to Define all the properties that align with their user for example and then set the respective types and minimum requirements here and then they're able to run user.parse pass in another object and then it will either throw an error or return the user as expected so let's go ahead and take a look at how we can implement this with our form so if we come into our source folder here and then go into routes and go to page.server.js we can see that we have a default action here that's currently just console logging the form data so when I click submit register here on this form let me go to my actual console you'll see that we have name email password and password confirm and then if we check this terms and conditions box we're going to have name email password password confirm and we have terms says on and on is the default value that's passed for a checkbox if you don't specify something else okay so we're getting all that information into our action here here now let's go ahead and set up our Zod schema so that we can start to validate some of this data so we're going to import Zed from Zod and then we're going to find a register schema it's a zed.object and then we're going to create an object so we're going to say we're going to have obviously name and then the name is going to be a z dot string and let's just say that we want it to be a minimum of one character which means that they have to pass something here it can't be an empty string and let's say the maximum is going to be 64. for example and then we want to trim the end which is trim off the white space from the end of the string and I'm getting all these methods here if you look at the Zod documentation you scroll down you'll see that they have strings listed here that have a handful of string string specific validations and there's also validator.js which has a bunch of other useful string validation functions that we can use so I'm getting all this here so please refer to the documentation it has a ton of information for things that might be useful for your specific data but let's move on to the email so we know that email is going to be Z dot string it's always going to have a minimum of one we'll set a maximum of 64 as well here and then we'll also say email now we don't need to run trim on an email because it just does that by default it parses out the email from that string and we'll remove any white space from the end so now with this object here let's go ahead and run a test run with our register form even though we don't have all the fields here I just want to show you what this also does so what we need to do is inside of our action we need to set up a try catch block because this is going to throw in error if we mess up with our validation so we'll say const results equals register schema dot parse and we'll pass in our form data object just like this right and then we went to console log if it passes or console logs success and then we'll also console log the result and if it fails the validation we'll say console log error we'll take a look at that okay so let's go ahead and run this first with nothing so if we click register we're going to see that we get a bunch of things but what we really care about is down here at the issues and we can see that we get a few messages that relate to each one of the fields and it says that the stream must contain at least one characters and this this path array here is actually the field that it maps to and we'll see that here in just a few seconds but it's giving us errors back okay for each one of the fields we've defined validation for so what if we just type in name and email and then we register you can simply get success and then we get the object right but if you recall we actually passed in a bunch of other things we passed in an empty string password a empty confirm password so it actually strips those out so if something is not specified here it will get stripped out of the return object by default right unless we can say that the field is required or it's optional so let's go ahead and Define our passwords now and we're going to build off of this and add some additional error messaging and then learn how to get it on the front end as well here in just a second so let's say the password it's going to be a string it's going to be a minimum of eight characters we'll just use six here and then a maximum of 32. and we also want to trim off white space from this and then the confirm password or password confirm will be the same because these should be the same exact values right and then for our terms right since we get that on what we can do is we can say Z dot enum and then we can pass in an enum and we're only going to have one option here and it's just going to be on but if you had multiple they could be listed like this or on or off for example right we're only looking for on so if it doesn't have on we want to reject that right we want to throw an error so let's save this here now let's fill our form and let's not accept the terms and conditions and you see that we get an error expected on right and it's required so let's do it successfully all right it was successful we get our object back just as we expect and then we could use this object to go and you know create a new database object or do whatever whatever we were planning on doing with that object in the first place but now let's look at making this more user friendly right because right now the user has no idea what's happening when this validation's gone behind the scenes they have no idea what's wrong of course we could show some error message here on the screen but right now it's just showing some you know required message right and that doesn't really help them or let's say the string is is must be at least one character that doesn't really tell them what what string needs to be one character okay so we can do is we can actually go into each individual one of these methods and we can define specific messages that will be shown if that is triggered right if an error is triggered from that that method so we can go into string for example and we can set up something called a required error which basically means if this is not passed so if a value if this property is not passed in to that schema and this message will be displayed so we'll say required error and we'll say name is required and then for minimum we can pass in a message and say name must be at least one character and actually for this one we'll just say name is required because and really in reality if they don't pass anything here if they don't pass at least one character then they didn't pass anything which we could just say it's required as well and then for the max we can say name must be less than 64 characters okay and then for email we'll do the same thing we'll say required error email is required for the minimum maximum say email must be less than 64 characters and then we'll say email must be about email address okay now for password again we can do the same thing here okay so we went ahead and set up all of our custom messages here I didn't want to bore you with watch me type all these in but let me change this back to password confirm because I copy and pasted this like a cheater and we can see that now we have nice messages here for each one of these validations that gets triggered so if if the minimum is less than one it's going to tell us that it's required because they didn't pass anything in if it's greater than 64 it's going to tell us that it has to be less than 64. so this is what these are the messages that you want to display back to the client or on the user interface side right what we can do is inside of our actions as you can see when we trigger an error we get this pretty big object here with a bunch of nested arrays for the paths what we want to do is we want to flatten this a bit and Zod has documentation on this if you look at their error handling documentation which I believe is they have a full page dedicated to it here I will be able to see that we're able to flatten errors we come down here we can see that we now just get form errors and field errors and the field errors have the property that we passed through it so for example in our case it would be name password email password confirm with the with an array of the errors that it generated map to that property so let's go ahead and do that and show you real quick what that's going to look like so instead of just console logging error let's console log error.flatten and now let's resubmit our form just blank so as you can see this is already looking much better we have an array for each one of our Fields our form fields and all the different error messages that this generated are listed here so what we can do is if we just say hunter for example we're going to lose that field error name because it doesn't have any errors anymore right so we're only going to return back the errors that we receive so what we can do is we can actually pass these into our client side and if you haven't seen my form actions in Smoky video definitely go check that out it'll definitely be a good prerequisite to this but what we can do is we can actually pull field errors out of this object here and we'll say const build errors and we're going to rename that to errors equals error.flaten right and then what we want to do is we want to rip out the password and the password confirm so it's best practice to not return the password back to the client if they're registering or putting in sense of information for example if they have a validation error we want them to retype in their password and their confirmed password so one of the easiest ways to strip out passwords or strip out values from an object we can just say con or I'm sorry const password password confirm dot rest equals form data and the reason we're doing form data here is because we want to return back the values they had in their fields before with the updated validation messages right so we want to give them everything except for the password and the password confirm so essentially this destructuring is doing is we're taking the password password confirm out and then everything else or the rest is in here instead of this rest variable right and we can obviously rename this whatever we want it doesn't have to be rest it's just a common way to do it so then what we can do is we can return data as rest and errors and that's going to give us access to not only the errors but also the values that were passed in the form field so they can make their Corrections without having to redo everything from scratch right so now let's go into our page.spel which contains our form and we will accept that form prop so we'll say export let form which is going to contain everything that we returned from the action here so now let's begin to update our UI to show those validation messages and we're also going to change the border of our inputs to red when a validation error occurs okay so since we have access to this form prop here we're also going to have access to the errors which means we're also going to have access to those field errors which are DOT name dot email and so on and so forth right so what we can do is inside of our labels we make this a bit bigger here as you can see we have a span class which has the label validation label listed here and it's hidden at the moment so we're going to actually remove hidden from this one for now it was just hidden because I wanted to already have it here when we needed it so we're going to say we're going to say if form dot errors dot name then we want to show this validation label and then what we actually want to show from this though is going to be the form dot errors dot name and then the first value from that array so if you recall we were actually receiving an array back for the error messages and we want to get the first one of that array you could obviously run in each block here and loop through all the errors and show them stack but for this example we're just going to show the first message okay so let's go ahead and save this and then I'll just go ahead and submit this form empty again and you'll see that we do in fact get name is required okay what if I send it as this okay we get nothing back right and that's because we're not actually having the value listed here so we go to a value on the input and we'll say form dot data dot name because we returned data right as rest and then we'll say otherwise nothing and as you can see as soon as I refresh the page we see that here so remember data was being passed here this is not the data that comes from a load function this is our other data so this is form.data which contains all of the initial fields from the form data all the initial values from our form data so now if I resubmit this again for example and I just put h it's going to give me H back if I put nothing it's going to show an error so now let's go ahead and add this same error essentially or the same label to all of our individual Fields here so I'm just going to copy this and then replace this span label on each one of these with the respective form errors dot whatever so this is dot email so I'm just replacing the name with email for password I'll do the same thing here and then for confirm confirm password or password confirm I always flip that around for some reason and then lastly for the X or terms now you can see since I just submitted it all these errors are still there but if I refresh the page let's just submit name is Hunter we're only getting errors on these if I accept the terms you know we're only getting errors on these three okay so we can go ahead and also add the value to each one of these fields as well of the ones that we're actually wanting to get back and the only ones we want to get back are actually the email and the name because we want them to re-accept the terms and conditions we also want them to re-add their password and confirm password right so under our email input we'll go ahead and paste this here and we'll change this to email so now if I type in an email I'm getting that back still from the form and it's still showing error messages for these which is great so now what I want to do I want to get a little bit more fancy here and I actually want to update the border of our inputs here to be red if there's an error as well so what I can do is I can come into my name form here and you can see input border is what's actually adding the border to my field so what I can do is I can actually set up some brackets here and I'm going to say I'm going to wrap this in a string I'm going to say form Dot errors.name then we want to show input error right because this is if this is true so if there's a form dot errors.name we want to show input Dash error I also want to show input bordered an input error just changes the border to red so now if I resubmit this form with no name you'll see that not only do we get name is required we also have the Border changed to red and then we can just copy this class for the remainder of the field as well and we'll just change their names here okay so you can see now that we're getting validation on all of these if I refresh the page again to clear those out I type in name and email now we only get errors for the password and confirm password right and then we can do something with the checkbox as well it's a little bit different so what we'll do is um for the check box down here where is it checkbox primary we can just say form errors dot terms then we want to show order red or border error I think we can use border error here okay so now it's showing it there but it's showing it by default so if there's an error show The Border error let's say order error otherwise nothing okay there we go so now we have this red we have all these fields all these inputs red if there is validation issues right so we're pretty much already done with the validation piece of this now there's one more thing you may have a question about and that is probably okay well how do I check to see if my password and confirm password match without breaking you know the structure of the errors and obviously you could add it to that array but that would get a bit messy so Zod actually offers something called super refine which if I go into the documentation here again and I look for super refined let's first look at refine seraphine let's just provide custom validation logic via refinements a super refine just gives us more control over that refinement right so we can take in a value as well as the context and then you're able to add your own custom issues so we're going to do that really quick to finalize this little validation project we're working on here so let's go into our page.server.js and then at the top here for our register schema object we're going to add that super refine method so we'll say that's very refine remember it takes in a value in the context but we can actually destructure this and say we want the password confirm and the password right and then again it also takes in the context as well and then we will say if password confirm is not equal to password then we want to CTX or context.ad issue and we're going to make an issue object the code is going to be custom because it's our own custom issue the message is going to be password and confirm password must match and then the path is going to be the name of the field so we'll just say password for this one and then we'll just copy this whoops copy this one more time and this one will be for the password confirm field okay so let's go ahead and test that test this out and see if it works as expected so I'll fill everything in as expected say password Here so I'm typing password and I'll type password one two three here and then I'll accept this right so let's hit register now we can see that password and confirm password must match that validation is happening so I think it's going to conclude this video I hope it's been informative I hope this kind of showed you how you can you know not only validate the input on the server but also you know display useful UI information to the user so they know how to make Corrections for their form submission to actually go through so if you got value out of this video don't forget to like And subscribe don't forget to join the Discord server if you have any questions you can ask me them in there and I will see you in the next video foreign [Music] [Music]
Info
Channel: Huntabyte
Views: 17,761
Rating: undefined out of 5
Keywords: sveltekit, sveltekit tutorial, sveltekit crash course, sveltekit +page.js, fetching data with sveltekit, external data sveltekit, sveltekit load functions, sveltekit props, sveltekit endpoints, sveltekit routing, dynamic page sveltekit, sveltekit url, sveltekit form actions, sveltekit forms, svelte forms, sveltekit actions, form actions sveltekit, use:enhance, sveltekit form validation, sveltekit zod, zod form validation, svelte form validation, sveltekit form errors
Id: 3PYdcm-HBiw
Channel Id: undefined
Length: 19min 31sec (1171 seconds)
Published: Mon Oct 24 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.