Go, Alpine.js & HTMX - Building a Small Todo App ( Golang )

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to show a small example of how to use go with alpine JS and HDMX we're going to show how we can pass data from our go backend into an Alpine component and we'll see how to render that data that's stored in the Alpine component in our goal template and finally we'll see how we can integrate HTM X into that setup in order to dynamically fetch hyper media from the go server in response to user actions in order to create a dynamic interactive page now there will be some starter code on GitHub if you want to follow along with this video and if you're enjoying this content give the video a thumbs up and subscribe for much more now let's dive in now to start with we have a GitHub page for the starter code of this project and we're going to use these two files that we have in the GitHub repository to start creating the content in this video so let's go to VSS code where I've cloned that repository and we're going to have a look at the code that's here in this starter code so we Define a struct called to-do here and that has the members ID which is an integer name which is a string and is completed which is a bullan field if we scroll below that we have a slice of to-dos here and we've defined three to-dos in that slice first one for learning go the second for learning Alpine JS and the third one says go to the gym and each of these have a status of is completed that is either true or false for that particular to-do and what we've also got in the starter code is this map here of templates so this map here has keys which are strings and the value is going to be a pointer to a template object object now what we're going to do is load these templates on program initialization and we're going to use the go init function to do that and if you want to know more about the inet function I've left a link to a digital ocean article on that what we're doing here is we are creating the map of strings to templates and then below the F statement we're adding the index.html template and that's the one that you can see here on the left hand side we're setting that equal to this statement here so what we're doing is we're paring the index.html file when the application is initialized and we're storing that P template in this map here and we can then use that map in order to get the P template whenever we have a request coming into our Handler functions so let's now look at the code below here we have a main function where we Define a single handle Funk and that's for the endpoint slash and that's going to call the index Handler that we have above and the only thing that we're doing in the index Handler at the moment is we're getting the index.html template which has already been pared and we're returning that template to the response writer using the execute template function and the context or the data that we're passing to that function we are just passing nil at the moment later on we're going to pass some data and that data is going to be rendered in the template in an Alpine component now if we quickly look at index.html this is a very simple template and it contains some placeholders for this table of to-dos and also below where we're going to add a form later in the video and use HTM X to send a post request to create that new to-do item and add it dynamically to this table above now let's start by looking at the Alpine GS documentation and what we do in Alpine is we Define a component using the X data directive X data it defines a chunk of HTML as an Alpine component and it provides the reactive data for that component to reference we can see a very simple example here we have a key called open in X data that's set to false and when we click a button we're changing that state from whatever it was before to the inverse of that so if open was false what this is going to do is set it to true when the button is clicked and when it's true that's going to set it back to false and Alpine allows you to build interactive Pages by referencing that state for example here if the open state is set to true we're going to show the content in this Dev otherwise that's going to be hidden from the page so that can be toggled dynamically by clicking this button now we're going to use an Alpine component in our application and what we're going to do is we're going to take a list of to-dos and let's go back to main. go here this list that we have above here on line 15 we're going to convert that to Jason and return it to this template here called index.html and then in that template what we're going to do is Define an X data directive and we're going to take that Json data and we're going to par that and add it to the component and then we're going to work with that data inside the Alpine component so let's get started with that and what we're going to do is go back to vs code and I'm going to go to this index Handler that we have here and we're going to write some code to convert these to-dos from that map to Json data now the variable's called to-dos here so let's call copy that and we're going to go back to the Handler function and when a request comes into this Handler before we return the template what we're going to do here is we're going to convert those to-dos to Json we can use the json. Marshall function for that and we're going to pass the to-dos into that function and the Marshall function will return the Json encoding of V we're going to store that in a variable called Json and we might also get an error in the conversion of those to-dos so we can get that error here we're then going to check if the error is not equal to nil in which case we know there's a problem here and we're just going to call the log. Fatal function and pass that error into that function otherwise we know if we get below this if statement that all has been good in converting those to-dos to Json so we're going to get the template here called index.html so we want to inject that Json data into the template so what we're going to do here for the third argument to the execute template function is we're going to define a map and that's going to take a string as a key and the values are going to be a type from the HTML template module in go and that's a type called JS now if we hover over this JS this encapsulates a nons safe ecmascript 5 expression and that's going to allow us to pass in that Json content now the value for this is going to have a key called to-dos and the value itself we're going to use that template. JS and we're going to pass in the Json that we got back from the json. Marshall function above so just to reiterate we're creating a map here as the data that we're passing to the context and that map has a key which is a string called to-dos and the value for that key is of type template. JS where we pass in the Json as a JavaScript expression so now that we're passing these toos into the context let's go back to index.js and we're going to create an Alpine component on this div that we have here in the template now before we do that we need to actually import Alpine at the top and we're going to go back to the documentation and go to the installation page in order to do that we're going to do this very simply using a script tag and we can get this one here and copy that and paste it in into our template here within the head tag so now that we have Alpine we can use these directives in our HTML code and the directive to create a component was the X data directive so we're going to Define an object here and it's going to have a key of to-dos and the value that we're going to get here is the value coming from this context variable called to-dos so we need to reference that here and we're going to use the go template syntax in order to do that so we're going to use the dot and then the name of the property is todos so let's clean that up so all we're doing here is taking the converted Json and we're setting the to-do's variable on our X data Alpine component and that's going to be equal to the value that's been converted and passed in from our go server so let's test this out I'm going to go to the terminal here and I have air installed on the left hand side so that we can do live reloading as we make changes to this code if you want to know more about that check out the video we did previously on air so let's run the air command and that's going to build our executable and once that's running we can go back to the browser and we have our page here now now there's nothing interesting here we have a table but we aren't rendering the data that we've converted in this table yet but if we inspect the document we can see now that we have an Alpine X data directive here on the div and that key of to-dos here now has this value that's coming back from the go server so we've converted that map of to-dos and we now have that data here client side on our Alpine component so we can now use Alpine to Loop over the data that we have here and render those elements within this table here so let's go back to our template and we're going to go down here now we have a table and we're using the bootstrap class of table and we're going to fill in this table body that we have and we're going to reference the data in our Alpine component in order to do that now I want to start by giving the table body an ID here so we're going to give an ID and we're going to set that equal to to-do table body and we're going to see why we're giving it this ID later in the video and that's when we're using HTM X to swap in some content into this table so let's now use Alpine to Loop over our to-dos so we're going to create a template here and we're going to use Alpine's X4 directive which serves as a for Loop essentially and we're going to Loop over each to-do in the list of to-dos that's stored in the Alpine component now for each to-do we want to create a table row within this table and we're going to create a table data element and we're going to fill in the text for this table data using the to-do that we have here and we're going to reference the properties on that to-do now the first one is the to-do's ID and we're going to close off this table data element and the reason for that if we look at at these column headers above for the table is that we have an ID column as well as the to-do's name and whether or not it was completed so what we're going to do now is we're going to copy this line of code down two more times and for the second column we're going to reference the to-do's name and finally the completed field now let's double check that these are the correct names here what we're going to do is go back to main.go and when we convert this map of to-dos this slice of to-dos sorry to Jason each individual to-do is going to be converted to Jason with these Keys here now we can see for completed we have this Json field here it's called is completed so I'm going to copy that and we need to change that here to is completed now because we're using air whenever we make these changes it's going to rebuild the executable and we can go back to the browser now and when we refresh this page we now have the table filled in with that data so that's very simple all we've done is we've taken the to-dos from the server and we've added them to our Alpine component and then within the template we now have this X4 directive and that's looping over each to-do in our list of to-dos and it's rendering each one out as a table row with the properties of that to-do in those columns now to demonstrate some interactivity using Alpine we can attach handlers here so for example if I was to click one of these elements what we can do here is set some behavior in JavaScript so for example we can use the alert function and we can alert out the to-do's name on the browser and this is just for demonstration we're not actually going to keep this code around but let's go back to the page and when we click one of these to to do we can see we get the alert message now we can use this Behavior to change some of the states so for example what I can do here when we click this we could set the name to uppercase by using the JavaScript to uppercase function and what I actually need to do is reassign the value of Tod do. name to that expression what we can do then is go back to the page and when we refresh this page if we click one of the to-dos you can see it has updated to uppercase now let's remove this Behavior now we're not going to need this going forward and one thing I want to just touch on before we progress in this video is why we might want to do this one of the benefits of having these to-dos entirely in the client side state is that it allows us to add things like a search bar and filters to this table and because we have the state stored on the client already the front end is going to instantly be able to update without that round trip to the server to do that filtering or searching and that's going to be very fast and reactive and it's a similar Paradigm to what react itself does and similar Frameworks like VJs and spelt but with alpine it's very simple in this case we have added a CDN link and we get access to that interactive functionality and we could very easily add a search bar or filters to this page now what we're actually going to do if we scroll down below the table is we have another section of the page and it's got a header of add Todo and we have an empty form element now this is from the starter code what we're going to do now is we're going to actually create a form that contains fields from which we want to add a to-do on the server and we want to use HTM X to do this eventually and when we create the to-do we want to get back a fragment of HTML that we can then add to the table dynamically all using HDMX so we're going to see how to do that very soon let's go back to this template now what we're going to start by doing is adding a method to this form so when we submit the form we want to send a post request and we need to Define where on the server to send that request so we are going to do that with an action attribute and let's create the action of submit to do so that's going to be a URL on server on the go application and we're going to Define that URL very soon what I'm going to do now is create a div and it's going to have a class of margin bottom two and we're going to duplicate that below and these divs are going to hold the form fields that are going to allow us to create a new to-do now the very first field we're going to specify the to-do's name so let's give it a label of to-do name and then we can define an input of type text and we'll give this a name here and let's just set that to name because it's going to be the name of the to-do and we can give it a class from bootstrap in this case and that's the form control class now let's close that input off and I'm going to copy these two lines of code just below here the second label is going to have the text of is completed and let's add a question mark to that because we're asking the question has it been completed and let's change the type of this from text to checkbox and we'll set the name of this field to completed and we don't need the form control class but we will give the field a value of true so when the checkbox is is ticked the value that's going to be sent to the server is going to be true now the last thing to do at the moment in this form just below the two Fields is add an input of type submit and that's going to allow us to submit the form to our go application now we need to create a Handler for this URL here called submit Todo so let's go back to the main.go file and let's scroll down to our function main we already have a call to handle Funk just above here so let's copy that down here and we're going to paste the new URL path in here and that's going to be submit Todo now we're going to set this to a function that we're going to write in a second and that's going to be called submit Todo Handler so let's copy the name of this function that we are referencing and we're going to scroll up and we're going to Define this function just above the index Handler so let's define that now and we can copy these attributes from the HTTP Handler functions so we're copying the response writer and the pointer to the request and now we can Define the logic of the submit to-do Handler now when we submit the form we're going to send a post request that's going to hit this function and that's going to contain data for the name and for whether or not the to-do is completed so let's go back to the function and we're going to extract that data from the body of the post request and we can do that and go using a function on the request itself and that's post form value so we want to start by getting the name of the to-do and the key that's going to be accessed here is name and to get whether or not the to-do was completed we can use the same function and that's post form value and we're going to get the field field called completed but that's going to be true if it's ticked and it's going to be null otherwise so we're going to perform a bullan check here and check whether or not this is equal to the string true so we've extracted the data that's been submitted by the user on the front end what we can do now is create a to-do so I'm going to do that by creating one of these to-do structs and the to-do has an ID which I'm just going to hard code at the moment to four it has a name that we're going to set to what we pulled out of the post request and finally it has a few or a member called is completed let's set that to the completed value on line 37 above so this is our new to-do let's just make sure this is working by printing that to-do to the terminal and let's just write a dummy response for now so let's now test this out by going back to the browser and we're going to refresh this page and on the right hand side you can see we now have the form so I'm going to add a to-do name here and in typically British fashion I'm going to say make a cup of tea and I'm going to leave as completed unchecked and submit this to the server now we get back the dummy response if we go back to VSS code and look at the terminal we can see we now have this to-do struct printed to the terminal it has the ID of four it has a name of make a cup of tea and as completed is set to false now let's try this one last time by going back to the page and all I'm going to do is check the is completed checkbox and make sure that this is set to true on the server and we see that it is now as a note you might want to validate and sanitize some of this information before you do anything with it that's going to be the dependent on what you're trying to do with this submitted data now instead of printing this to the terminal what we actually want to do is we want to take the new to-do that we've created here and we want to return a new row that can be added to our table that we see here and this table consists of different table rows for each to-do when we create a new one we want to return an HTML fragment with the data for that to-do and we want to have that added automatically added dynamically to the table that we see on the page here so in order to do that we're going going to add HTM X into the mix but let's start by creating a new template fragment that's going to encapsulate this task let's go back to VSS code now we have an index.html file here I'm going to create a new one and let's call this too. HTML this is going to represent a single to-do item and that to-do item is going to be a single table row with table data elements for each column in the table now the First Column was the ID column so we're going to add that here and again let's copy this down two more times this column was for the name of the to-do and the final column was the is completed member of the to-do structure now what we want to do is save too. HTML and go back to main. goo and we want to add this new template to our template map that we created on initialization so we've created index.html by passing that when the go program is initialized let's copy this to the line below and we're going to change the name of the key in that map and it's going to reference too. HTML and the template that we're actually passing here is also to do. HTML and again if you're wondering why we're doing this a lot of people commented in the original goal in HTM x video that we should not be passing templates on every request within the Handler so one way to deal with this is to pass them when the program is initialized using a map or something similar like this so let's go back down to the submit to-do Handler and we can remove the last two lines here what we're going to do when we actually create the new to-do here is we're going to append it to the list that we have or the slice that we have up here so let's do that to begin with so the to-dos slice we're going to use the append function here and we're appending to the existing to-dos that new to-do that we've just created once we've done that we now want to return the template fragment to- do. HTML so we're going to extract that from the map here so let's go back down here and create a template variable and we're going to set that equal to the map here and let's index in to the map and get the element with the key of too. HTML so that's going to give us back this P template here here and we can now return that using the same function that we used here and that's the template. execute template function let's paste that in and the first argument to that is going to be the response writer the second is the name of the template and that doesn't matter too much but we'll just call it too. HTML and finally the third value is going to be the data that's passed to the template and that's going to be the to-do that we created here on Line 39 from the data from the post request now let's save this and we're going to go back to our page and on this page if we refresh the page and submit a to-do here and again make a cup of tea let's submit that and what we get back is the HTML content the table row now we can see the data has been filled in correctly here but we shouldn't be getting back the HTML itself what we want to do is take this Table Ru and add it to the existing table that we can see on the page here now let's add HTM X into the project because when we submit this form we want to use HDMX to send that post request and we don't want the page to refresh we want that to send an Ajax request and refresh the content dynamically using HTM X attributes so I'm going to go to the HTM X documentation and I'll leave a link to this below the video we're going to copy this script tag from the CDN and we're going to go back to the index.html template and let's go to the top in the head tag and paste that in there now this is going to be an alternative to the Jango video that we did recently on the same topic in that video we had a similar setup and we used the Alpine Ajax plugin for Alpine Js in order to do the dynamic fetching and swapping of hyper media content from the back end in this video we'll change that up and we're going to use HDMX if you're interested in videos with the Alpine Ajax plugin let us know in the comments but now that we have HDMX in this application what we're going to do is we're going to add HTM X attributes to the form so that it sends a post request using HTM X when the form is submitted so let's do that now and go back to index.html and scroll down to our form that we have here now rather than specif ifying the method of post we can add the HX post attribute here and set it to this URL that we have in the action attribute so I'm going to paste that in here and we can remove the action attribute and we're going to set a target for the response content which remember is going to be this too. HTML template and we want that to be swapped into the document at a particular Target and it's going to be this one here and that's the table body we want to add the new table row to the table body so we're going to reference the table body here using this ID we can do that by adding the id symbol here of the hash and pasting that ID in now that's a very simple change to the mechanics of how that form is submitted but we can now go back to the page and I'm going to refresh this page and add a new to-do and when we submit this what's happening now is that the response content and remember that's the table row that is actually going to replace the inner HTML of the target element now the target element is the table body so if we inspect the document here we should still have the table body but all of the content that was in the table body before has been removed and replaced with the template fragment for this new table Row from the server now if we want to keep the table rows that were already there which you would probably want to do we can change the swap strategy that HTM X is going to use when it receives that hyper media response from go so let's go back to the template now and we're going to add one more HDMX attribute to this form element and that's the HX swap attribute now what are we going to set this to let's go back to the HTM X documentation and HTM X offers different ways to swap the HTML returned into the Dom the one that we are going to use is this one here it's called before end and that's going to append the new content after the last child inside the target so let's go back to the template if we look at the Target which is the table body the last child of that is going to be the last table row inside that table body and when we get back our fragment here containing the new table row if we set the HX swap strategy to before end it's going to append that new table rule that's coming back here to the existing table body after the last row that's already in the table so we've added one simple attribute let's now go back to the page and we're going to test this out by refreshing and adding a to-do so let's select make a cup of tea and submit this and you can see that that is now added to the table it's not removed all of the existing rows but it has added the new row at the end of the table and if we add one more and check is completed you can see that that is set to true in this table now of course we're hardcoding the ID that you see in this table so if we submit many of these all of them are going to have the ID of four and a normal application that's going to be handled by the database and if you're interested in those videos on using go and HTM x with a database then let me know in the comments and if we refresh this page you can see that the table rows are all preserved even though we're not using a database and that's because when we submit a to-do it's going to create that to-do and a append it to the existing slice and then if we refresh the page the new request is going to come into the index Handler and that's going to take that slice with our new appended to-dos and it's going to convert that to adjacent data here and pass that to the template using this to-dos key and therefore in the template if we go back here and go up to our div here we have an Alpine component using X data that's taking those to-dos so any new to-dos that are added are preserved until the go server is refreshed so if we refresh this and inspect the Dom we can see all of the to-dos including the new ones that we've added are converted to Jason and stored in the Alpine component now these are not persistent on the go server so if we go back to our application if we make any kind of change here and save that you can see that that's rebuilt at the bottom because we're using air and because the server has restarted all of the to-dos that were added to this slice have been lost and when we go back to the page and refresh we now get only the hardcoded ones that were in the main. file so that's all for this video we've learned how to take data from our go application and that could come from a database and in this case it was hardcoded but we've learned how to convert that to Json and return it and store that data in an Alpine component and then use Alpine directives like X4 to Loop over that data and directives like X text to show information on the page from the data in our component and what we also did was we added a form that's allowing us to submit a new to-do to the server using HTM X and and that request is going to be sent to the server and the server will return a template fragment that is going to be swapped into the document and added to the end of the table now you wouldn't strictly need to use Alpine and HDMX together in this project but I did want to demonstrate both aspects in an application that wants to use HDMX for that hyper media and also Alpine perhaps for interactivity and to convert some data to data that can be stored in an Alpine component for that very quick client side filtering and searching that you can do if you're using alping so that's all for this video if you've enjoyed this video give it a thumbs up and subscribe to the channel for more we've got much more to come with go and HDMX let us know in the comments if you have anything that you are particularly interested in seeing thanks again for watching and we'll see you in the next video
Info
Channel: BugBytes
Views: 7,131
Rating: undefined out of 5
Keywords:
Id: Gf9L7XA1X8Q
Channel Id: undefined
Length: 26min 21sec (1581 seconds)
Published: Tue Mar 19 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.