Building Full Stack Golang + HTMX + Templ APP

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what is Up Guys in this video I'm going to start by teaching you in a very pragmatic way the basics of HDMX creating components with temple and how to integrate everything with goang that way you also get a feeling out of what we're going to be building and then after that we're going to code this whole project from scratch together take note that this project is simple by Design because the goal of this video is to teach you how to integrate these Technologies together and give you a heads up on hmx and and these Technologies so I've kept the functionality really simple just to a simple crude system and what we're going to be building is these list of uh for example a car show where you can add cars you can list them search for them and you're going to even Implement an active search so for example has I type here the results are going to be changing in real time the whole application is not refreshing this is just HTML no JavaScript and with that you can see that we can replace all of the JavaScript functionality with HDMX while this is an introduction sometime in the near future I'll be making a complete production ready full stack application in HDMX and goang so stay tuned for that one and if you're not familiar with HDMX it adds a bunch of new functionality to HTML and making it capable of building complex user interfaces with just the power of hyper media let me just show you here for example on the docs for example when you click a link you can expect the page to go to this link but here on HDMX um and when you click the link the page is going to refresh and you're not going to have that feeling of web application and htx gives us the ability to make requests from any element to the server for example take this example we have this button where when we click it's going to make a post request to this SL clicked endpoints and the trigger here is clicked but this is the default behavior for the Buton so and it's targeting this div for this ID and it's going to swap its outer HTML we're going to see that in in an example in a bit and I think it's going to click for you if you didn't uh got this example and then the the trick is that on the server we are going to be responding with HTML and then replacing the content on the UI um and not the whole page for example I got a list of HTM Max and this list got swapped just on this element here and not the whole page right and the same is going to happen when we add instead of returning the whole list we are going to just return a new car tile and added it to the start of the list now the white that we're building is going to be served from the server as I have explain you so I think this tool Temple is a really good combination with HDMX because we can just create elements in go and how crazy is that and it's really easy to understand as well so this is an example of a component and this is how we're going to be building our components so let me just explain you how the listing of the cars work here so how are we displaying this and how the project Searcher handles that and then we're going to check how this car handling works and how we can Implement that together uh before we start the project right so here I have on the main go um basically I have this main function it's initializing the routes uh the database and I love that stuff and if you check this handlist card this is a get request the first thing it does is it gets the cars from the database and then it goes to the Views which is going to be in a temple file and we just pass in the cars so if you go inside this View and then of course we render it at the end and inside these views you are redirected to this autogenerated file um so we are not supposed to edit this file here it's this one that car Temple this is where the templating is done so you might see that have a temple instead of a function this is syntax from Temple and if you're wondering how to get the syntaxing Highlight in vs code I have list here on the read me how you can set up the project just like the one I have I'm going to leave the link below in the description basically um follow this link here and you can get started there so the listing basically um this is just simple HTML but here below I have the components. car list and this is receiving the cars that we just passed in if you go inside the cars list it's just a list are lists that Loops over the cars so this is the power of Temple so we can just write a goang loop here in just HTML and it's going to translate into um a list of these card tiles and this card tiles is another component that it just has static information about the cartel so here is the Del button which has some functionality uh but then here I just the display image and the text uh the name of the C and all of that good stuff so again the flow is very simple we just did a request to some storage and we are redirecting with HTML instead of being Json how an restful API would be for example right this is the only change that we are making so let's start by implementing this adding of a car feature and what's happening is that if you click on the ad car button a new UI is going to show up on the screen and if I just click cancel I go back to this initial state so we can just move in MO move out but after we click here on this second ads the car should be added to the database and then shown here on the UI on the first style or at the end of the list for example so here on the HTML I just have here a form with is inputs and here you can see this um this logic so if the is adding car state is true we show this form otherwise we just show uh the the cancel or ad car right but these are just inputs uh texts that are just holding States whenever click adds this button should trigger an event on the form that sends to the post carard so this post uh handle at car we should call this in points which creates another structure with the car so the brand the name and the model then we create the car on a database and at the end we just return a car tile which if you remember it's this small implementation of the car so that's static uh tile there and not the whole page so that is the goal so how do we get started let's go back to the cars. SLE which is the page and here on the form let's go back to the documentation and if you remember this button it does a request we can do this so for example let's just replace this and it have been clicked it's cars so if we just click this button right now let's try to make here uh Hondas Civic Type R for example from 2020 and why me just add some random image and if I click on ADD I can see that the form just disappeared and this caral just swapped it so something is working but something is also not working so if you take a look at the logs on the network the request was successful so we send in the request with every parameters from the form but the response and has it should it return just this car tile right it's correct just return this card tile but here on the form it is replacing the the whole form what we want to do is Target this list here and add the new element to this list and and if you remember that we can do that with the Target and the swap so let's go ahead and choose in the Target and the target is going to be the car list ID so where does this come from so I have here the components of the carore list and here I have the ID car list and if you take look at the browser here this is the whole list that we want to add a new item so this L item it's that Carle so let's target that's div and then what we want to do is swap it and what's the strategy for swapping it here on the documentation we can just search for the Swap and there is multiple properties we can do that so the um the one that want is actually this one the after begin so prepends the contents before the first child so at the start of that list and now let's try again the the adding so let's go ahead and add the car now and we can see that the car was added at the start of the list and the return is the same it's still a tile so you can see how this works and how intuitive it is and if you go back to the list now uh here we have the the car added all right guys so with that out of the way let's get started by coding this project I'm going to start with this starter code here and I'm going to explain to you why and what it does and what I have here basically I want to focus on the HDMX goang and Temple so I have this just simple structure that I usually use on my projects if you want to learn more about how to build an API in goang I have a video on the description that I have made on the channel you can follow it and the structure is going to be pretty similar which is how I do my all of my projects and basically here we have the the store interface and the implementation for it this is how we are communicating with the database so not going to go over it it's very simple just a crude application and this is the interface that we're communicating with for the service then here on the main file we just initialize the database um you can also get all of this codes in the description below as well if you want to follow along there and then here we just initialize the store service the storage and the router here I'm using gorill Max for that and um you can easily Swap this with standard Library as well it's very easy and then I'm just having here a handle funk for the handle home which renders this um this View and if you go here to the Views I just start with this home. stample which is just this car show example everything here is wrapped by this page and the page is where we have the basic HTML uh so here we have the uh The Heading the title of the page and this is where we are going to add HDMX and Tailwind as well so the first thing that we need to do to get htx is let's go back to the documentation and let's go to the introduction and here somewhere should be um an installation so we are installing via the CDN so we can just go ahead and copy this line which is going to install the latest version good then we just need to Wi and the way that we are installing Tailwind is that here I have on my mic file a command that it requires the Tailwind CLI if you want to know how to install the Tailwind CI go here to the read me and you can just click and follow this installation for your environment but after that you can just do make tailwind and what it's going to do is it's going to go to the Views so here CSS and styles so this basically Imports tailwind and then it's going to convert all of that Tailwind to the public SL Styles so if you just run this and cancel this execution you can see that when you go to public Styles here you have the whole tail winds generated for your project so that is how we're going to install thewind but here on the HTML we need to reference that file here that to loads these Styles right and to do that we just have a very simple link reference to that uh file right nothing special so this is it and here we have the spread operator as well so we can just wrap uh Pages like this like so we can just wrap them and if we want to have a navigation bar we can just say true otherwise just say false and we are controlling State on this wrapper page now you might be wondering why is this error uh here so we have the views and the home here um the home Temple they are created why is this component not being detected and the thing is that when you saw that those go generated files just gibbish those were actually the components that Temple generate so we have this Temple files these are the cative um cative structure but we need to generate them in order to be um compatible right so let's go ahead and do a make Temple and this is It's a watch process so we can just cancel it for now and what it did is that it generated a couple of files here so it generated this home. temple. go this is the go um code for that template and here the error just disappeared after that so whenever you are generating a temple make sure to run these commands what I recommend you is to always keep um three processes running so for example I usually have the the make Temple and then I have on another window the make Tailwinds so the Tailwinds and the temple files are always being generated as I type so when I save the file it generates and if I go to the browser the UI changes automatically without having me to reload the page and then we just start on listening the API on this port 880 so um let's just go over this init function and basically what it does it starts database connection and for that we need to um I'm going to show you how you can do that as well so here I have a Docker container running my SQL and basically here on my database what we can do so I just created a new database called cars you can do the same if you go to the config um db. name you can just change the name of your database for example mine is called curs and what we do now is that here I have I have a tool called migrate here I have some migrations so we can start your own database so this is the up and this is a down again it populates with some data that we saw on the demo to run this just go ahead and do a make migrate up and it's going to generate the tables and populate everything so if you go here I have here the cars table and the data generat this is just an example so you can get up and running fast and finally to run the the go server I'm running this tool called error uh you can see again on the read me file it's everything there basically this is a hot reloading for go so whenever I change the file the whole server is going to be recompiled very fast it's very powerful as well so I just type airor the server is running so connected to the database everything is working so we can just go ahead and do make Tailwind as I've shown you and finally the make Temple and it's going to open up the browser so this is what we start whenever you click the cards on this link you can see that nothing happens we got a 404 and this is what we're going to be implementing in this video so let's get started by creating ourselves this new end point because if you take a look at the page. temple more specifically the home. temple you see that this link here it's an H so nothing special it should redirect to new page even here here on the page. temple here we have the nav bar and whenever you click on the button we should be redirected to an end point so it's going to make a request to the server so let's go ahead and make a router. handle Funk and the route is Just Cars and here we should have something but the method is going to be a a get sorry and the Handler is going to be for example handle uh CS list and let's go again here at the let me just close this file at the handlers I'm going to create a new Handler domain which going to be the cars. go and let's create a method for the Handler so this is going to be a method inside of the Handler the Handler is just this stct that we just initialize it in the May file it has a service so this is a dependency of the storage why is this made so we can easily test this whole thing without depending on storage implementation so I can just inject this remind remind you this is um the storage truct which implements the story interface so we can easily mock this as well even just passing here the story as well it would work um so let's go ahead and do the handle cars list it's going to receive an HTTP response writer and a request after that the first step is to get the cars from the database so let's go and consume this storage I know that this is going to be on store get cars and you don't need to pass anything let's just easily handle the error for now we're not going to take a look at it let's just log it error and then let me just return we can handle this better at later stage but for now let's focus on some value for the application and here what we want to render is a page that we do not have which is going to be called for example cars or cars list I'm going to keep this cars um just going to keep this comment for now uh let me save the file and let's go ahead add the views so this is going to be a page a view I'm going to call this cars. Temple and inside the temple file we are going to Define this inside of the package views and to make a component in Temple we just say Temple instead of being Funk it's going to be Temple very similar and you call this C cars what is going to receive it's going to receive a type of these cars which is going to be a slice of types. car if you take a look at this it's just this structure and direct mapping from the datab base uh structure and here we just return some HTML something uh let me just import the car like this because I'm lazy and then let's just have a simple div just saying cars list view okay so here the compiler should do the work if you take a look here the cars. temple has a cars. go here and if you're wondering about this dxt this is just for development purposes this is what Temple does behind the scenes I don't know much about it but you can ignore it um here we have the views package and now we have access to the cars we can pass in our cars can render it to the reader context like so and pass in the writer has a second parameter we can save this and here I think everything is done let's save this as well let's go back to the project let's try the flow again so if you click on curse we should be redirected to this view here and it is working so you see that something is missing the na Bar is missing so this experience is not the best let's go back to the temple file of the cars this one and let's rub as you guys saw a component for the um the page so it's a page say that we want naar and we just wrap what we did here let's go back to it we just refresh we can see that the list is Now seamless here right so here I have just quickly styled a bit the page so it looks a little bit more decent uh Center that title and let's go ahead and start rendering the cars so I'm going to show you how you can create a component um so let's just make a smaller component instead of being a page it's really the same idea uh just how we divide it it that's how what matters so I'm going to call this cars list. Temple so here let's just create the cars list right so whenever we save the file should be generated here as well awesome what we want with the cars list is just rendering a simple order list and then we just Loop over the car so let's receive here again the cars slice types. car and then here we're going to Loop over this structure and render something here so let's create again another component which going to be the carard tile do stample car tile and this one is going to receive just the um the types doc itself and here if you go back you can just access the component like this so we can access because it's in the same package we can just do this card and we pass in the card inside this like so it's actually got CLE so this is going to be the list now let's add some styles to the C otherwise we're not rending anything and here I have quickly styled this so I just added some classes from Tailwinds uh here I have a span with the car brands the model this is how we access the properties we can just have all of these prop properties here very easily and then here the image as well so the last thing that we need to do is then again render the list that we just created right so let's go to components do car list and rendering the cars that we just received which I forgot what here the name cars so if you just save and let's go back to the application we can see in real time that it just got the whole list of the cars right here so let's go back to the home click here you can see that we have the whole list so at the start of the video I showed you how you could add the cve and all of that jazz but let's go ahead and do something different and let's start by creating the Del of the car on the list so let's have here a button below and whenever we click it we're going to delete the clicked um car so how can we do that again first thing is that we need an endpoint so let me just copy this it's going to be a delete and let's call this handle delete car let's go back inside of this and just create a new function because just going to copy these parameters here because I'm lazy and then the first thing that we need to do again is called the store so let's go store delete car we need to delete the car in the database but somehow we need to get the hold of an ID how can we do that let's think about it so let me just save this file let's go back here to the to the cars list inside of the cars. tile so our goal is to have here a button so let's just create that button so whenever we click this button we want to delete this carard how can we identify this carard we can use the car ID to identify it and how can we pass in the ID so if we go ahead and make here HX do delete so remember here is the verb we could be a post a put something is going to be a delete because we decid this to be a delete here so the end point is going to be slash cars slash ID right doing vers and then doing max.vs and then we can access the ID by doing verse slash ID and accessing directly this property so I could check that the ID is valid all of that I'm just going to send this to theit car get in the error and handle it and then here how we do this so instead of rendering something we are just going to write a header and I'm going to do is going to be a status do HTTP do status okay okay we're going to go back to this in a bit so keep that in mind and here we pass in the requests um so let's go back here to that now so we are accessing this delete but how do we delete this exact element so let me show you what is happening here so if if I click on deletes now we get an error of 405 and if we check the logs we see that again something failed here and it makes sense because the URL does not have the ID right so whenever we clicked this delit we need to somehow pass in the URL to this the ID to this URL right how we do this is that we can just concatenate the string so fmt do sprintf just like you do in go and pass in the format so it's going SL cars slashin a decimal and then the value is going to be the cars. ID so if we just save and go back and click on the delete we can see that we got a 200 something happened nothing responded but we see that this button just disappeared and as you know this is the default Behavior we are deleting the button it's being swapped by nothing because we return nothing and there is a very interesting thing that we should take into consideration which is when we delete it's going to Target the element itself so we want to Target something else so for example here it is targeting the body so let's go ahead and Target in what we want to Target it's this whole tile and to identify this tile we could add for example here an ID again we need to add in um a generated ID so s print F it's going to be for example car and then we just pass in car. ID then the target is going to be this here that we just wrote the ID and we are targeting be by the ID so this part here is important if it would be a class it would be like this so this is basic targeting um HTML syntax with the query element so it's the same syntax if we just refresh this page here and we hit delete we see that this style disappeared so we are almost there but we are not deleting so this is swapping the data and not deleting and if you take a look at the documentation we need to go here at the HX swap strategy and there is a strategy to delete so it deletes the target independently of the response so let's go ahead and add the final piece which is the swapping let's save so whenever you have problems with the the swapping everything works but the element stays there or it it's not added correctly it's usually because of the Target or the swap so check that so let's go ahead and try to delete this masterda tree and if you delete it we see that it just disappeared and this is again the response if you refresh this the car is gone from the database and from the list so that is how you can Implement theion from this list and there is a very important detail that I want to mention you and no one told me and it's something that you could leave you some hours of debugging hell so to remove the element from a successful delete return at 200 and not a 200 at four because it will not take the swap in place so here on the the end point when we return the right header okay if we just return 20 104 it would not take the swap into consideration so don't forget that when implementing deletion always reads through the documentation so to finish everything off I just want to show you how you can implement the searching because I think it's a more complex feature so let's go ahead and go back to the cars list Temple here I have just added this very simple input and we're going to build the active searching so what that means is that as we type something here the list is going to be changing and showing results debounced so if I just type a lot of things and I stop it's going to do a request if I uh delete it's going to make another request and it's not going to make a request on every key strike because that is very slow it would make x amount of requests which at the end of the day we just want the uh the key right so the first thing is that we need to make a request so it's going to be a get it doesn't make sense to do anything else and we are going to do SL search we're going to search for the name then we want to Target the cars list so this is the cars list we don't have this ID yet so let's go to the car list. Temple and add in this ID to the list go back so whenever whatever the search end point returns we're going to re replace the whole list with the results and then a trick here is that the trigger is not going to be the click or anything else it's going to be a key up or key changed with a delay of 500 millisecond so how easy is this right this is just implemented what I have said which is that key uh request so whenever this meets it's going to make these requests with this delay of 500 so whenever I do this it's going to make a request as you see here if I just type a lot of stuff going to make another request if I delet this it is um removed and if we deleted this delay here then as I type x amount of requests would be made and you can see how how bad is would be for the server with just bombarding the whole server with useless requests let's go back to the main following the same strategy let's copy this and do a cars search it's going to be a get going to move this here and then it's going to be handle car search again very easy here I'm reading the value from the form so this this is going to be the search inputs I have named it search here so this is the one then I go to the database and I find Cars by name or brand or make uh and then I just have the cars from that search then we just render the components. car list that we we already have pass in the cars the new ones the fields and we just say the context and then the writer as well so this is it basically for the search uh let me just handle car search save this there was a typo and let's go ahead and test it right so let's go ahead and search for example for mazes and we see that we got all the mazes and if delete this let me just open here the dev tools for the network if I search for the Toyotas we just get the Toyotas and if we this we get all the cars then because I have just deleted a bunch of them uh there's just one to back if I search for the MX5 Matata I get the mxi meas here as well and there is just a problem here let's take a let's take a look at the HTML so you can see that there is a double list here and again this is very common HTML problem HTM X problem what is happening is that we are uh we don't have the exact swapping strategy that you would we want so let's go back to the inputs and add an HX Swap and the strategy that we want is the outer HTML So currently it's the inner HTML if I'm not mistaken and we want to return and swap the whole Outer HTML of the car list so let's go back and refresh this search for the MX5 and you can see how fast this is that the search is and you can see as well the list is fixed so again if you search for Toyotas the list Remains the Same and it doesn't add other layers um as we saw previously and it's also interesting to see how the HTML is changing on real time and not the whole page we're not making any um page requests so this is it guys this is the power of this stack and I'm honestly I'm going to build a complete project uh in the future with this whole stack production grades so uh stay tuned for that one and with that I think I have shown you how you can build this project even further and add those edge cases that I've shown you which are very valuable it would be very valuable to me at least when learning um so let me know if you guys like the video give a thumbs up and consider subscribing and check the channel because there is a lot more content like this there so see you on the next one
Info
Channel: Tiago
Views: 12,180
Rating: undefined out of 5
Keywords: golang, htmx, templ, a-h/templ, full stack, full-stack
Id: yqDYYjbatfE
Channel Id: undefined
Length: 34min 54sec (2094 seconds)
Published: Tue Feb 27 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.