Multistep Forms with Laravel & Livewire!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey welcome back to another video this video is going to be on multi-step forms with livewire something that was requested by someone else in a previous comment section and i found the idea pretty interesting i just haven't had the time to put the project together but this is what i came up with now i have this demo project here that i would consider the final final version of what i want to build in this video and basically it's just a a page in the in the breeze dashboard on a relatively fresh laravel project and you enter your first name last name email address so for me it would be like this and the validation should fail on each field so if i reuse the email that i'm currently logged in with it should throw an error and or it should show an error rather and now it should let me get to the next page here i'll enter a password if the passwords don't match it will give me an error if i make them match it will clear the error and allow me to submit and that user should now exist in the database here is a fresh database of the starter project this is what the project looks like now and we're going to take this and transform it into what you see in the final version i've already logged in with an account i created you can see it in the database here testtest.com and basically by the end of this video we should be able to create new users with the full validation thing working all of it done let me show you the starting project here so what i've done is i've created a new layerable project i'm running php8 i have everything set up with valet on a separate development domain i've installed livewire i've installed breeze and i've already created the component with the tailwind and html stuff just to save some time if you're interested in tailwind related stuff i have plenty of videos before this that you could watch and you'll probably find value there i don't want to spend too much time on tailwind in this video because it's just going to get way too big and i'm going to lose my place and it probably won't bring you that much value so let's just start with the web file i've created a new route here with it's slash user slash create it goes to the create user form component and it uses the auth middle where it has a users.create name in here the component is empty and but in the template i've already created set up all the html that you saw in the starter starter application here so all this is what you're seeing in the file and we're going to make that work i've also added the app.blade.php so as you can see i've created the or added the livewire styles livewire scripts here this is something you have to do when you're installing livewire with breeze i believe like it there is an app.blade.php that livewire expects to be there and you have to add that in there what's interesting about the breeze dashboard is that it expects a header right so the header you see here is the header here and so inside the template file i've also used an x slot with the name header to just add that in there and that's what you're seeing there so this is the starting point i think the first part that we need to do is just make the correct form fields show up in the correct pages so to speak and make those buttons work once we have the different buttons working we can flip between pages of the form we can then make the actual submission work then work on the errors the success message and along the way get all the heading and subheadings working so let's get started for me is going to be just declaring a couple public properties in here that we can use in our template so public current page i'm going to set this to default to one and i'm also going to create a public pages and here we're going to track the heading and subheadings that you see in the starter here so heading subheading these should change based on the page we're on within the template okay and in here the first page should be personal information because it's just name and email and i'm going to call page 2 just password and the subheading should be enter your name and email to get started and down here let's make it create a password for the new account that should work the added benefit of having pages declared like this is that we could actually just use count pages to get the total number of pages which we're going to use for the submit button in a second i'm also going to create a couple public functions here first one's going to be go to next page and i'm going to use this to increment current page there's a little bit of setup involved here i know it may not make sense now but as we go through the template it'll start making more sense so go to previous page and we're going to do the same thing just decrement so current page minus minus and that should be fine on the component side let's go ahead and start implementing that here first thing i'm going to do is use the current page to get the correct heading so how i'm going to do this is actually just use pages which is now available in our template current page heading and down here we're going to use similar thing pages current page subheading and now if i refresh the page here we're going to get an error because we're not using a dollar sign so if i refresh now personal information enter your name and email to get started perfect because we're on the first page so now let's go ahead and make sure that our correct fields are showing i'm going to zoom one way just to get a better view here we have one containing div here containing the name first name last name email address and then another one containing the password and confirmation this should be page one this should be page two we're just going to use an if here to make sure that we're showing the correct one so if current page is one else if current page is equal to two and down here we could just use an end if i'm going to indent these just to keep it clean in the in the template file we can refresh and see that only the first name last name and email address are showing which means that the password and confirm password are actually being hidden and so that works for now now it'd be nice to actually be able to click these buttons and go to the correct page the interesting thing here is that you see three buttons and there's going to be an empty div here we should only see either two buttons or one button and an empty div based on the page if we're on the first page we should only see the next button that's it if we're on the last page we should see back button and submit if we're on some page in the middle like page two out of three we should see back and next i hope that makes sense so we're going to implement that now let's go ahead and just go to our button section here so as you can see i'm using flex item center justify between if you're not familiar with tailwind what this means is flex is obviously flex using flexbox item center will align it vertically justify between will push two elements or however many elements there are as far away from each other horizontally as it can so if you have two elements and justify between it will push those two elements to opposite ends of the containing div in our case if i have an empty div and a next button they will be opposite of each other but if i have no empty div here and there's only a next button like on the first page then the next button will probably be at the left side of the box the containing div which doesn't make much sense so that's why that empty div is there let's go ahead and get this implemented and it'll probably make more sense the first thing i'm going to do is actually check if the current page is equal to 1 because we want that containing that empty div to be visible there and here i'm going to do add else because if it's not page 1 then we should have a back button and div and if and let's indent these here we're going to want to check if we're on the last page and that's where that public property pages will come in because we could actually count how many pages there are and then check against which page we're on and that's how we're going to know if we're on the last page so at if current page is equal to count of pages if it's not else oops else and if let's indent these make sure it looks good refresh the page here and see what happens so we have an empty div here you can't see it that's why the next is aligned here actually i could probably just remove this temporarily you could see that without that empty div the next is on this side which doesn't make much sense now i could have dynamically set justify between to only be added if we're not on the first page i'm not a fan of that in uh we're using like the the the blade helpers because it just looks ugly it's not view and so i just prefer doing it this way so if i click next here it should take us to the password but it doesn't because we haven't implemented the wire click yet if i click the back button we should wire click to go to previous page that public method we we defined earlier go to previous page we'll just decrement the the current page if i do the opposite and click click next we should go to next page now if i refresh and click next you can see we go to the next page our password and confirm password fields are showing all the other ones are hidden and our headings have changed so it's password create a password for the new account so far so good of course our submit button doesn't work yet well it it's submitting the form in the most basic way html knows how to but there's nothing really defined on how to submit data where where to put it you can see that it's just trying to add it to the uh to the url here so what what we're going to do now is implement that basic submit button without any validation and see how far we can get there the first thing i want to do is actually define wire model on all of our text inputs here so you can see first name last name email address password and password confirmation but they're not actually linked to any public properties in here so let's define those and then and then link them in the template so public first name public last name public email public password public confirm password so we also want to confirm password because we're going to be validating and this will come in handy and now we could actually go ahead and just link these in here so wire model dot lazy is equal to first name the reason i use dot lazy is because when it comes time to implement validation i don't want the validator to be running on every keystroke every like every time you type a letter um it's just not necessary so dot lazy will only run the validator when you've clicked away from the element next we can do wire model dot lazy equal to last name oops wire model dot lazy equal to email and down here we could do the same thing let me just copy this password and confirm password so let's make sure that these are the same and they're spelled correctly and they are and now we have these available with the data for our submit method which doesn't exist yet so we can create one now let's create a submit method and in here we can create a user which we need to import create and we need a name which i'll fill in in a second we need an email which would be this email and we need a password which would be this password now keep in mind nothing's being validated this is not great but we will implement a validator and the reason i wanted to fill this in last is because the database uses one name column but we actually take a first and last name input separately the way i'm going to get around this is just by just concatenating them together so first name this last name and now this will be fine so if we go back to our form now refresh and let's just try it so david and do uh test let's see what's already in the database so we got testthattest.com if i do test test dot com test2 at test.com next and just make it password and password and hit submit still won't work because we haven't actually defined where to submit to in our template and so up here in the form we can do wire submit dot prevent to prevent any kind of weird refreshing stuff and just specify that we want to use the submit method something to note um we have a submit type submit button down here for the submit button and you're you're going to want to make sure you have type button on any button within a form element because our form element closes here you're going to want to use type button on it because if you don't i've had instances where buttons that were not meant to be submit buttons were treated as submit buttons so i always kind of use type button to make sure that doesn't happen now if we go to the form refresh without this stuff try again test2 at test.com next password password submit nothing happens but if we go to our database i think it will be in there and it is so we can also kind of make this nicer by resetting our fields and the way i want to do this is by just calling the the livewire helper reset and this will reset our fields to whatever they were originally i believe so if i refresh now just do test test test three at test.com next password password and submit we can see that it takes us back to the original page and the first page and also resets our fields here and i believe if we're lucky yes we have test3 at test.com in here which means that it actually worked now of course we forgot one thing we have to hash our passwords because you don't want to store them in plain text so i forgot to just wrap this in decrypt and that should solve our problem with that i will actually delete these two records and that should solve that so the next step will actually be implementing validation as you can see it's kind of annoying that we have both of these showing that's not how it should be and also if there are errors on page one or any page before the submit page the last page we shouldn't be able to click next that just doesn't make sense so that's what we're going to do next okay so this might get a little tricky because we need to keep track of validation rules based on the page we're on and so we're gonna have to define rules a little bit differently than we would normally and before i do that i just want to go through and actually make sure that our our stuff is set up correctly so that these error uh alerts don't come up when there are no errors so what i'm gonna do is actually just wrap this in an errors if if errors is not empty and if oops i forgot the at and i'm going to indent this and down here i'm actually just going to go ahead and and do the same for the success one because we just need it out of the way so it's easier to see what's happening now you'll notice that the success public property has not been set but i will set that in one second so success end if i'm going to indent this and in here let's just declare a success so public success and we could actually already set this down here so this success is equal to user created successfully and of course once we have validation implemented we can assume that if the execution actually gets down to this line then it would have been submitted successfully regardless because validation will happen before the user is created anyways so let's refresh and see if that changes anything okay so those are both gone now we need to take care of these guys and what we're gonna do is actually i've already included the spans here for errors and so we just need to wrap them in the at error stuff and then in our case we could just do at error and in this case the key would be first name i believe in here this would be message so we can replace these all at once just to make our lives easier and we could go to the end of the span and do end error and then i'll just go ahead and manually add these everywhere with the correct naming and now we should be able to only see these error messages if there are actual error error messages for these keys within the airbag i can go ahead and actually declare my my error validation rules and like i said i'm going to do this a little bit differently than you normally would with live wire i'm going to make this private and i could have squeezed the error validation rules in here if i wanted to track by page but there's no reason to make the actual validation rules available within the page when you're using livewire's built-in protected rules array that you can use or declare within your your component it is protected for a reason i think so for me just declaring it private to keep within the the component class is fine i don't want it to go to the template i'm going to call it validation rules that just kind of makes sense to me and i'm also going to use the one and two keys for the pages the only difference in here is i'm going to remove this and i'm going to remove this and this is where our validation rules are going to live so first name let's make this required and a minimum of three characters long this may not make sense in the real world but let's just do this so it's easy to show that the validation actually works last name will be the same and email will be also required email and it has to be unique on the users and the email column okay i hope that's making sense now for the second page because the second page has a password and confirm password i'm going to make it password and then confirm password and both of these are also going to be required so i could just copy and paste these in and we're going to make these string minimum of 8 and this one's going to also be a string it has to be the same as the password field above it and it also has to be a minimum vape that just makes sense so these are my validation rules now it is great grayed out in my vs code because it's not used yet but i can now use it in here the only trouble is if i use the built-in validator from livewire it's going to expect an array of just keys instead of an array of pages with the keys within it so i found a way to get around this and i can actually demo this in here so within tinkerwell what i've done is i've actually copied in the validation rules here and as you can see it automatically just kind of runs it and it's it's giving me the same thing back here now if i want to just grab one specific page's rules i could just use it like an array with the key if i want to get all rules like i need to for the this arrow validate what i need to do is just collect them and i'm going to do this by hand just to show you what's happening so if i collect this it'll just wrap the same thing in a collection i need to collapse it which will remove those first keys exactly what we need but this won't work either because what's happening in this validate which i can show you right if i click into this you can see that it's actually going to expect an array and so what i'm going to do is just in tinker well i can just call to array and this is exactly what we're looking for we're looking for the keys with the validations and and this is available for all pages at once because on the submit button we definitely want to validate every field not just the ones on the last page i hope that makes sense so let me remove this and let's actually implement this so this arrow validate and let's call just rules and we're going to get rules here so rules again let's collect them so this validation rules collapse to array maybe there's a better way to do this but this actually worked for me and so so now we're validating based on these rules and now technically if we go and we try to submit if i refresh the page and i try to do this next and submit these are required these match and they will pass but it won't allow me to submit and yet there still are errors by the way our alert works which is great there still are errors but it won't return me to the page with the errors this is kind of a difficult thing to figure out what i ended up doing was implementing validation on every next click if you get from one page to the next that means the previous page validated completely and so i'll never have the situation where there's something failing on page one or two despite everything passing validation on page three so at least we know that the validation works if i remove this and make it something that doesn't match and click submit we're going to see that the confirm password and password must match our validation is working now i'm also going to include this if we submit successfully and a record is created we're also going to reset validation this is also something that is included with livewire and is super helpful and i'm just going to include that now before we forget so the way i implement that per page validation is basically by calling the validator on the go to next page method so this validate and it's going to be the same thing as last time except if we go back to tinkerwell here i'm only going to use a key to get the ones i need so i'm going to use the current page to get the exact ones i need and within here we can do it this way this validation rules current oops current page and so now if i refresh and go here test test test that's not a valid email if i click you can see the email must be a valid email address and now i will never be able to get to the next page and actually submit the form if these values do not pass validation and so what if we want to implement that the validation when we click out of an element and try to click into another one we want to do that automatically well that's also something that's built into livewire and it's something that i think is pretty cool what we can do is actually just create a function here a public function and we can call it updated and updated receives a property name and we could use that property name to validate only that property and so what we're going to do is we're going to call this validate only and typically you would just in pass in property name and you'd be done with it because typically you'd have a rule a protected rules array here with the validation on the same level already collapsed and live livewire would be smart enough to kind of already figure out what to validate against this property name and so in our case what we want to do is if we actually click in into this method here we can pass in a field which is a property name and it defaults to null rules because it'll actually go ahead and and figure out the rules messages and attributes by itself somewhere in here and so we can go ahead and just figure out the rules from our validation rules array here and i'm going to pass in property name and then i'm also going to pass in this validation rules this current page and this will actually end up working exactly as it would had we used the typical livewire way of doing stuff and what will happen is if we're on page one and we're validating email it will go ahead and get only validation rules for page one and then live livewire will will look into this array and say okay property name is email so we need to validate email we're gonna use this and that's what's gonna happen there this is actually updated and now if i refresh and type in one letter here because the minimum is three and i click into last name you can see that the first name must be at least three characters i can do the same thing there and i can also put in a random string there and you can see that it says the email must be a valid email address it will not let me submit because it will fail validation so that's fine we've we've accomplished pretty much everything the last piece of this puzzle is to figure out the just the success message alert if we submit a successful one so let's try that next put in a password that matches by the way we are validating everything here so test should throw an error it does submit and if we submit we can see that we have in the database that record with the hash password and we have this user created successfully message but we can't remove it so this is kind of like the last little thing to implement and we can do this very easily just by creating a method called reset success we could call this reset and then pass in success specifically which is something that live this method from livewire allows you to do you can just pass in the success key and it will reset only this and now within our template we can find our success alert which would be i believe right here and i think this is the actual button so we can do we can just do wire click reset success so now let's create a real user and make sure we can log in with them so let's do my name again real user.com copy this password password submit this we can now clear this message refresh message doesn't come up again we can log out log in using that email password we can log in so the the password is hash correctly everything works and that is the completed multi-step form with live wire tutorial i hope you enjoyed this video a couple notes before i end this uh i don't know if livewire is the best uh tool for this job i feel like managing pages within a php class is probably not the way to go i work with inertia and view it at work and that seems way better suited for this use case so if you are thinking of building something like this i would definitely you know reach for javascript uh and and just use laravel as your back end it just seems way more it seems to make more sense to manage pages in this kind of managing state within javascript uh than than it does with with php just something to note i hope you enjoyed this video i just recently crossed a thousand subscribers so to anyone subscribed thank you to anyone not subscribed please do consider subscribing i enjoy making this vid these videos and we'll continue to do so thank you for watching and i hope to see you in the next one
Info
Channel: David Grzyb
Views: 4,704
Rating: undefined out of 5
Keywords:
Id: 1_FndV_HfME
Channel Id: undefined
Length: 29min 36sec (1776 seconds)
Published: Sat Apr 17 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.