HTMX in Laravel - AJAX calls with HTML

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up guys Andre here and today I'd like to take a look at htmx htmx allows you to perform Ajax calls and update Dom Elements by making use of plain HTML attributes it expects a response in HTML as opposed to Json which is probably what you're used to and this can help simplify the process of updating the Dom there's been some recent hype around htmx and I was just curious to see how it can work with a few practical examples now you need a back end of some sort so you can return the desired HTML from your endpoints and of course we'll be making use of laravel for this so let's go into the docs here it's really simple if you take a look at this example here we have a few HTML attributes HX post is the endpoint we want to use it supports all of the HTTP verbs like get post put patch and delete trigger is the event we're listening for in this case click on this button Target is the element we want to insert the data coming back from the server so in this case an element with an ID of parent Dash div and swap is how we want to replace that element so in this case outer HTML other options include inner HTML before and and so on and I'll show you a few examples of that as well so how about we grab this let's go to our welcome blade so welcome.blade let's get rid of all of this let's start from scratch let's say htmx and we'll paste that button within here okay and we have to install htmx so let's go to installing I'll just do the CDN here but there's also an option for npm but let's just grab this let's put it into our head and I will also defer it okay let's change our Target to message and let's create that right here so say div with an ID of message and our swap is set to Outer HTML so when the HTML comes back from our server it's just going to replace this entire element which is fine okay so if we go to our routes file we can Define that clicked endpoint so this one that we defined right here but for any non-get requests laravel makes use of a csrf token so we have to pass that in as well and if you're using a form here we could pass that in as well but since I just have a button I want to bypass that csrf check so I'm just going to Define our route in routes API because this does not have the csrf check middleware so we'll add that clicked endpoint so route post slash clicked and remember the end point is going to be slash API slash clicked if we Define it in this file and how about we just return something here and again if you're working with Ajax you might be used to returning Json here but with htmx we want to return plain HTML so for now let's just do it in a string and that should be fine let's say clicked close out that div let's save this let's go back to our welcome blade and let's change this endpoint to slash API slash clicked so let me save this let's go into our application in the browser Let me refresh this and hopefully our Ajax call should work actually let me open up devtools here the network tab is opened so we can see that request happened let's click the button and you can see it did work up here you can see the request here and you can see the response right here again it's just HTML that we're responding with let's go back to our runs file here you probably want to write your markup in Blade that should work fine so let's return a view instead say return view this can be any view it can even be a blade component let's just say test so make that file right here in our resources views folder test Dot blade.php let's just make this a div say I was clicked we can even pass data into here if you like so we'll pass in a variable called Foo and let's pass that in from here just like we're used to so say Foo bar okay so now this should work the same way if I refresh this click the button it does work with a blade view instead you can even easily add a loading indicator so let me show you how to do that back to our welcome blade how about right here let me just make a span with a class of htmx indicator and also give that an ID of indicator okay and say loading and you can put whatever you like in here for example an SVG spinner but this should be okay for now and within here we can say HX indicator equals what we just created here so in this case indicator and how about I put a sleep on here to simulate some lag sleep two and now we should have that loading indicator so if I refresh and hit click me there's a loading indicator and there is our response so yeah super simple to make Ajax calls all done through HTML attributes okay now let's take a look at a few examples I have prepared here oh I have one prepared at contact let me just hide devtools here and if you scroll down you can see we have a typical contact form here and it does work but it's just a typical response with a full page refresh so I believe if I enter my name here or my email this is my message should work but it's going to do a full page refresh and scroll back to the top so it's not an Ajax goal so that did work there's the success message and the email should have been sent though but again that's not the best experience because again it's a full page refresh and it Scrolls to the top so for example if I had errors here it Scrolls to the top and then we have to scroll back down to see the errors so it would be better if we had some sort of Ajax call so we don't do a full page refresh so let's go ahead and convert this page to make use of htmx so let me just show you the code for this merrot's web we have slash contact that's just a view and this is the post request that has some validation here's the mail actually being sent and then we just return back with the success message and for the blade file contact blade PHP just make sure to import htmx as well so we'll grab that from here let's grab this and let's paste that in here okay so let's go ahead and convert the form to make use of htmx so let's look for that form right here let me just reformat this and let's go ahead and add our HX attributes so if you have HX attributes it's going to ignore the default so we can just leave these three here let's make a post request the slash again we'll stick with the API routes but you can pass into csrf token as well and that should work in the routes web if you want to do it that way but like I said I'll stick to slash API slash contact okay let's add an HX Target so what element do we want to replace we'll make an element with an idea of response so this will be where our success or error message goes HX swap in this case inner HTML or other HTML should work fine I'll stick with inner HTML because that's what I have in my example app I'm referring to and now let's create this element here so I did with an idea response I'll put it right here so response okay let's save that and let's take a look at our current endpoint so all of this and we'll move this to our routes API okay so we'll put it down here make sure to import mail and are available which is not really important in this example and if you're curious the mail does get sent out and it's currently set to the log driver so you can see the mail being sent over here let me just delete that for now and we'll work on validation in a second let's see if we can get the success message and the actual email sending out so assuming validation passes the only thing we have to change is this line right here so instead of redirecting back we need to return a view with the success message how about we do that so say return view let's say contact success okay and let's go ahead and create that let me just duplicate this one we had earlier for test duplicate contact success Dot blade.php and I believe I have a snippet here for a success message I believe it's this one here so we don't need the session variable or the check for it so let me remove that we can just put the message directly in here so say message was sent successfully okay and how about I put a margin bottom here let me save that and let's go back to our contact blade just so you can see what's going on so we're going to make a request to slash API slash contact it's a post request again assuming validation passes it's going to send the mail and then return this view contact success this is just our success measure Style with a green background and that is going to replace our HX Target which is a div with an idea of response right here the swap is set to enter HTML So within here it's going to inject this so let's see if this works let me just undo this did I not save contact success save that okay and let's give that a try let me hard refresh this let me just put in an email here this is a message and let's try this out and that didn't work if you take a look at the network tab you can see contact success not found and that's because I did not spell it right of course okay let's give that one more try it's hard refresh email message here let me just close devtools for now send message and you can see we do get that success message and the email should have been sent out just to double check the email let's go into our learn about log and there's the email now what about our validation error messages so if I just refresh this and hit send message you can see something happened here but we don't get any validation messages so let's fix that actually you can see we have two contact forms now and let me try to explain why that's happening so the validation is failing so let's go back to our routes API so right here it's failing and it's not expecting Json so laravel responds in the typical way and that's just the HTML for the entire page with the errors on it but we don't want that we want to return our own view with just the errors so similar to what we have here but for our errors so we have to make one small change here and that's to make use of the validator manually so let's comment this out let's say validator equals validator make let's pass in request all and our validation rules in here so it's the same thing as this space that in uncomment that make sure to save that's import validator okay and now we can check if the validation fails with validator fails so if validator fails then we can return a view with the errors so similar to this we'll make a new view called Contact error space.in but we'll also pass in all of the errors so errors is validator errors okay so let's duplicate this contact success but now contact error contact error blade PHP okay and again I have a snippet here for errors I believe it's called validation errors or errors error validation and we don't need to count the errors here because we already know there are errors so we can get rid of this if and we are passing in this error bag and we're using for each to go over them and then displaying them in this list item so this should work let me save this and now hopefully our errors should show for validation let me hard refresh let me send message and message sent successfully that's wrong and that's because I forgot to change this to contact error save that try that one more time send message and there are our error messages so again we're performing Ajax calls here but we are not using any JavaScript we're just making use of HTML attributes and then returning the desired HTML to be replaced into our Dom so one more case I want to fix here that's when we have a success message here send message okay we get this but I want to clear out the form here and I'm not really sure if there's some sort of event you can hook into and maybe perform some light JavaScript in this case to clear out the form inputs but the solution I had for this is to just replace these elements as well so let's go ahead and do that so only for the success case because when there's an error we want the input to stay there for our contact success contact success we're replacing this div with this but we also want to replace our inputs and just clear them out so these inputs right here so this and the text area and we already have IDs on them so we have ID message and ID email so we can Target these as well in the contact success right here actually let me grab the entire input here so let's copy this it's going to contact success so this is being injected into our HTML like you saw but we also want to inject this when it's successful so it's going to look for the same ID but we have to add one more attribute here and that is HX swap oob so out of band equals true so it's going to see this as well it's going to see this attribute it's going to look for this ID of email and then Swap this in the contact form and that should clear out the input again that's kind of Overkill not sure if there's a better way to do it you can make use of Blade components to dry up the code and not have repeated code but let's just see if this works let's do the same for our text area so I will grab this let's put this in here let's grab this attribute space that in and let's see if the input gets cleared out after a6s message here send message and it does clear out the input okay let's take a look at another example here at slash users it's almost the same thing as our contact form but we also have this list of users that we want to update as we add new ones here so if I add one here create user again this is without any Ajax so it does a full page refresh and Scrolls back to the top but it does work so you can see that new user here but we want to make use of Ajax and HDMX for this so let's go ahead and do that so again basically the same thing but we have to update this list of users so let's start with the validation in this case users.blade.php oh and the code if you want to see it in our Rob's web again basically the same thing here's the view we're passing in all of the users and here's the post request we have some validation and we are just creating a new user here and redirecting back okay so let's grab this endpoint because we're going to put it in our routes API again it can work in here as well if you pass in the csrf token but since we're already doing everything in routes API I'll just put it there so let me paste that in here let's start with the validation let me import this first and it's the same thing as this scrap all of this actually and let's just replace our validation rules with what we have here okay paste this in here let's comment this out let me just delete that since you already have it in Rod's web let's change this to users error we'll create that let's make sure to import hash and we will take care of this case in a second let's duplicate contact error and name it users error and this will actually be the same thing so we can reuse the other one as well but I'll just stick to using this file okay let me save this let's go to our users blade PHP and let's update our form as well and it's basically the same as what we had for the other form let me just reformat this so HX post is going to be slash API slash users HX Target we'll make this in a second same thing Dave with an ID of response and HX swap inner HTML okay and I already have that right here actually so let's see if our validation messages work save that back here let's refresh let's hit create user and that's still doing a full page refresh because I forgot to import the script for htmx so let's grab the one from contact up here make sure to grab this as well and put it into our user's blade up here okay save that hard refresh try one more time and it does work okay now let's work on the success case so again almost the same but we have to make sure to update the list of users so let's go into our route let's grab what we have up here but we'll make a new view for this so let's put it right here and say users success let's duplicate contact success named users success okay let's change the username here user was or the user success message created successfully and we do want to clear the input so we can do the same trick here again this code is duplicated but you can make use of Blade components if you like so let's grab the name input from user's blade look for input here for this one grab that put that in here make sure to add the HX swap or b equals true and same for the other field so let me remove this let's grab our other input so this one right here for email and that should work as well let's grab this paste that in here save that and that should work but it's not going to update this list but let's just see if it works for now with the success message let's say another another at another.com create user okay so we do get the message the list is not updated but if I refresh it manually you can see that person there okay how do we add the person we just created into this list here so back here we can do the same trick to update another element so what we want to do if we go back to our user's blade we have that on ordered list of users right here let's actually add an ID on this say users and after we add one we want to update this list and add a new list item for the user we just created so we added this ID of users let's go back into our let me save that first actually go back into our user's success let's add another element in here so we want to add another list item so I tried just adding the list item in here so we need the user so we need user name and user email like this and we have to add this HX swap oob on this element as well but we're not going to set it to true we're going to set it to before end and the element we want to insert it into so users now I thought this would work but it didn't and I might be doing something wrong here but to get it to work you have to wrap it in a parent div so let me cut this out let's wrap all of this in a div and let's put that attribute on this div okay so now it's actually just going to add this to the end of the list of our users which is what we want so now hopefully I did everything correctly let's add a new person in here add their email and hopefully Elon gets added to this list here after I hit create and we're getting an error because I'm not passing in the user here so you can see I'm making use of username and user email I forgot to pass it in to Our Success blade so let's say user is the newly created user which we will grab from this create so user is this and hopefully that should work now let me just remove Elon from here and try again delete try again hard refresh okay let's try adding Elon again Elon musk.com create user and you can see we do get the success message and our list is updated as well cool and there are different options for replacing the Dom in our case we just added it to the end of the list if you want you can replace the whole list of users as well or if you want there's also an option for using something like morph Dom so it only replaces new content instead of replacing the whole thing okay let's take a look at one final example here and that is this search filter so as we type here we want to filter this table and only show results for whatever you typed so I just have the UI in place for this it's not currently doing anything so if you take a look at our blade view so it should be search.blade.php we have our table here 's our input and we have this table here so we want to replace this entire table as the user types so this would be a good example to extract to some sort of Blade component how about we grab all of this let's cut this out let's make a new blade component named about table users and we want to pass in the users so say users equals users okay close that out let's go ahead and add that here let's make a new file let's put it within components table users.blade.php and space.in and that should work hopefully let me save this as well let's refresh this and it still works but now we have it in a blade component and we are going to be updating the users here again based on what the user searches for and based on a query that we will formulate so again let me just reformat this input and let's add our htmx attributes in here so let's say HX let's make it a post request I'm not going to do all of the fancy stuff like have query strings in here I just want to keep it simple and get it working so let's say hxpost the endpoint will be slash API slash search we have our trigger and we'll do that in a second let's just add our Target first and this will be table users actually that should be an ID and we have to give our component an ID so we will right here table ID equals table users okay save that let's go back to our search and let's add our trigger so our trigger is going to be on key up we also want to say it changed so only update if something in the input actually changes so it won't be triggered for things like just pressing the shift button we can also DeLay So this would be like a debounce so requests won't be sent until the user stops typing for a certain amount of time let's say delay above 500 milliseconds you also have to say search here comma search to be honest I'm not exactly sure what that does but we are using an input type search here and you can clear it by hitting X here and when you add search here it makes it so it updates when you hit that X okay so let's work on the endpoint so route API we want to make another post request here called search okay and we want the request in here so this is whatever the user types in you have to make sure to import request and let's go ahead and make use of eloquent here so say users equals user query and then search for name for now and we'll add email as well name like and how about we add a wild card in here so we'll say percent and request search so whatever the user types in and let's make sure to close that out with a wildcard as well and we'll add email after we get it working so let's just say get for now and we can return a view here return View and we just want to return the table with the updated users and we already extracted a blade component for that so we can just use that so components dot table users and we can pass in our updated users here so users is users okay hopefully I did this correctly and hopefully our search should work it's hard refresh let's look for me here and of course it doesn't work and again I forgot to import the CDN link for like the third time so let me just do that quickly so let me paste that in here save that hard refresh let's try searching for me and it's still not working we're getting post method is not supported for API search and that's because I have a get request should be post or get should work as well if I just change it in here so HX post but I'll just stick to post here let's try searching for my name here doesn't seem to be updating still it might not have the request here so if I go back to Search Blade if I look for my input yeah this needs a name on it if it doesn't have a name on it it's not going to pass it into the back end similar to atypical back-end form so let's say name equals search and hopefully this should fix it hard refresh search for me and now it works awesome let's try the x button here okay does work and currently it's not searching for email but we can easily fix that okay so let's update our query so we have an or where clause so back here we can just say or where email like request search so now it should search for email as well hard refresh let's look for this email and that does work as well cool so there you have it guys a few examples of using htmx with laravel it's simple approach to performing Ajax calls with only HTML attributes is definitely interesting and can be useful in certain cases now if you're wondering if I think this could replace something like Livewire generally speaking I'm going to say no Livewire has so many amazing features especially with the latest version that was just released and it can easily be the backbone of your entire app stack however as you've seen in the examples in this video if you just have a simple Ajax code that you want to perform and update a simple Dom element on your page then htmx might be a good fit so yeah definitely give htmx a try
Info
Channel: Andre Madarang
Views: 9,517
Rating: undefined out of 5
Keywords: htmx, htmx laravel, laravel htmx, htmx ajax, ajax htmx, laravel ajax, ajax laravel, laravel livewire, livewire laravel, laravel no javascript, hateoas, Hypermedia as the Engine of Application State, htmx tutorial, htmx django, htmx in 100 seconds, htmx vs react, htmx vs vue, htmx vs livewire
Id: ZUGejA3qRgI
Channel Id: undefined
Length: 29min 9sec (1749 seconds)
Published: Fri Aug 11 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.