Alpine AJAX - Alpine plugin (bringing HTMX-like functionality to Alpine!)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to look at the Alpine Ajax plugin for Alpine JS and this is an extension that allows us to fit hyper media from a server via an Ajax request and then brings that content into the document at a given Target element now this is very similar to HTM X it fetches hyper media from a server and it replaces Targets in the document in a particular way but it does this as part of the Alpine ecos system so it's going to be a different approach that we're going to show but it's going to be very familiar if you're already aware of how h XX works and how it might integrate with alpine so before we get started it would be great if you would give the video a thumbs up and subscribe on the channel if you've not already done so and let's dive in we're here on the Alpine Ajax page and as it says it's a plugin that enables your HTML elements to request remote content from the server and this can be used in a similar way to HDMX to build straightforward robust and interactive websites now in this video I'm going to show an example with d jangle and I'm going to do a follow-up video with go but these Concepts can be used in any backend programming language or backend framework now I'll leave a link to this page below the video we're going to go to the reference documentation here and we can see how we can install both Alpine and this extension Alpine Ajax so we can do this via a CDN which we can just Place into our HTML files or if you're using npm you can also do it through npm as well you can just run the npm install command and it'll bring that into your project so what we're going to do is to keep things simple we just going to copy the script tags here and we're going to place them into ajango project so I'm going to copy these and let's go to VSS code where I have a jangle project open and I'm going to go to the templates directory and we're going to go to a file called base. HTML and at the top here I've got an import for bootstrap I'm going to paste the Alpine and Alpine Ajax Imports into this document now the order is important here if we go back to the documentation you can see that you have to import Alpine Ajax before you import the core Alpine GS module now once we've done that what we're going to do to start with is take a quick look at the usage section here now the documentation says it's good practice to start building your UI without Alpine Ajax so you can make sure your entire website would work as if Alpine Ajax was not available and then you can sprinkle in these Ajax functionalities at the end let's have a look at some of the attributes that are added to Alpine JS by this extension or this plug-in we have the X Target attribute here and what this does is it's something you can add to your form or your links to enable this Ajax Behavior so if you're familiar with HTM X this would be similar to something like an HX get or an HX post attribute and not only those attributes but also the HX Target attribute itself because the value of this attribute should equal the ID of an element on the page that the form or the link should Target so let's take a quick look at the example here we have an unordered list with an ID of comments that contains a single comment below that we have a form element and this form contain contains standard attributes such as the method when it's submitted which is a post request and the action which specifies the endpoint where the posted data will be sent and that's an endpoint on your server whether it's D Jango or laravel or whatever you're using but notice these attributes here we have some Alpine attributes notably we have X init on this form element and we also have the X Target attribute that's added by the Alpine ax extension and that's set to the element ID here of comments and that targets this un Ed list that we have above so basically when the button is clicked and we submit this form the value that has been entered into this input element will be sent to the server and that will be done in an Ajax request because of this x Target attribute added by Alpine Ajax now this plugin expects to get back hyper media content so some HTML that we can then swap into the page and that content can then be swapped into the page at the ID of this target here so we have an unordered list and that has the ID of comments when we get back a response after submitting that form the response content is going to be swapped in and it's going to replace this element here with the ID of comments that's the default strategy we'll see later in the video how we can also use different strategies just like you would do with the HX swap attribute in HTM X so that's a bit of explanation to get started what we're going to do now is go to our jangle project where we have now the Alpine and Alpine Ajax Imports and to start with let's look at the jangle View and this is a very simple view called index it has an empty context and it's returning a template called index.html now above that we have some to-dos here and each to-do has an ID a name and an is completed field we're going to use these in this video and we're going to build a simple table of to-dos along with a form that allows you to submit a new to-do to the server and use Alpine Ajax to send that request and swap in the response content so let's get started we're going to start by adding the to-dos to the jangle context that we have and that we're passing to the view so let's create a key called to-dos and set it equal to that value above of course in a real project you would probably use a database here but we're going to keep it simple just to show the functionality of Alpine Ajax in this video now what we can do when we have a list of dictionaries that have been added to the context is we can actually create adjacent string from them in our template so let's go to index.html we have a very simple Jango template here and we're going to create some HTML in that template so we're using bootstrap we're going to give it a class of container and that will give some margin to the top top and to the sides and we'll create an H1 tag here and we're going to call this to-do list once we've done that we're going to take the to-dos that we have here in our context and we're going to create a script with Json content based on that data now in order to do that we can use the to-dos variable in the context and we can use D jango's Json script template tag and let me try and spell this correctly and we'll give that an ID of too list now if you're not familiar with this we did a video on that previously it should be appearing on the screen now this is a way to get your data from the Django server into the context of your document on the client and we're going to see an example of that now so let's start the Jango development server here and we're going to go to the browser at localhost 8000 now you can see on this page it just has a header that says to-do list but if we inspect the document here what we're going to do is go to the body and we're going to look at this container that we added and notice this script tag here and this is the type of application SL Json so this is Json data and the to-dos that we had on the server are now present here here in this Json data so what we're going to do is create an Alpine component and read this data when the page loads and later we'll use Alpine Ajax to add new data dynamically and fetch hyper media from the server so let's get started with that and go back to our template on this container div we're going to create an Alpine component which we can do using the X data attribute and what we're going to do here is set this to a JavaScript object and we'll give it a key of to-dos and we're going to now read the to-dos from this script here and this parameter of to-do list you can see that is the actual ID of the script so we're going to use that ID and we're going to use some JavaScript to read that into this variable in the Alpine component so in order to read that we can use the document. getet element by ID function and we pass to-do list into that we're going to get the text content from that and that text content is just going to be raw text but we can call the json.parse function in JavaScript and don't forget to close the function here and that's going to par that text content and create a JavaScript object from that data what we're now going to do is create a table element and show these to-dos using Alpine JS so let's go down here and we're going to use the table element and give that a class of table from bootstrap now the table needs a head with the column names so we have columns for the ID the name and whether or not the task or the to-do was completed so you can add the table head elements here and then what we're going to do is we're going to add a table body here and importantly we're going to give this table body an ID and that's going to be to-do table body and the reason for this ID is going to become a part later but we're going to use that as the target when we're using Alpine Ajax in order to send and fetch data from the server so that's our table body with the ID what we're going to do is we're going to use a template element now and we're going to use the Alpine GS X4 directive here so X4 and we're going to Loop over the to-dos that we have here in our context so let's go back to the template element and We're looping over these it's going to be to-do and to-dos so for each one of those to-dos we want to perform some kind of action and what we need to do within the context of an HTML table is create a row for each to-do and then we're going to create a table data element and use the alpine x text directive and we're going to reference that to-do and we're going to reference the properties on the individual to-do for example the ID of the to-do I'm going to copy this line down two more times and as well as the ID we're going to reference the to-do's name and whether or not it's completed which is the is completed attribute so is this going to work let's go back to the browser and refresh the page and we're currently getting an empty table at the moment let's go to the console and it looks like I've made an error here document. getet element ID is not a function so that's my mistake if we go back up here it should be get element by ID so well done if you noticed that let's now try this again go back to our page and now we get the elements in this table on the browser so we have the to-do Learn Python and that's currently not completed learn Alpine is also not completed but go to the gym was completed now what we want to do now is add a form below this stage that allows the user to enter a new to-do and we're going to use Alpine Ajax to send that request to the server and the Django server in this case is going to get that request with the data and it's going to use that data to create a new to-do object and return some hyper media back to Alpine Ajax that is then going to be swapped in at that Target element so the next step is to add a form below this table let's go back to our page here and just below the table what we're going to do is create a form element now let's give the form a method here and we're going to submit this using a post request and let's also give the form an actual endpoint to submit to so we're going to use jango's URL template tag and I'm going to create a new endpoint called submit to do now because we're submitting with a post request let's also add the csrf token to this submitted data and we can close off the form element now to speed things up I'm going to paste two Fields into this form the first one is going to be the name of the to-do item and we're going to surround these with a div with the class of margin bottom two to give it some space between this particular field and the ones below and then we have an input element and that's an input of type text where we can enter the name of the Todo item and we're giving that the bootstrap class of form control which is going to add some nice styling to that now as well as the name of the to-do we also need to indicate whether or not the to-do has been completed so let's add another field to this form and that's going to be for checking whether or not the to-do is completed so we're giving it a type of checkbox and the name of that field that we expect on the server is completed and the value is true and the final thing to do is allow the user to submit the form using this button that we have at the bottom so we have an input of type submit and again using the bootstrap classes of button and button primary so that's the form we're not going to be able to see this because we have added a URL that does not currently exist in the jangle project so let's copy the name of that URL and we're going to go to the urls.py so we're going to add another path here and we'll give it the route of/ submit and we're going to reference a view called submit too that doesn't exist at the moment but we're going to create that in a second and finally because we give the URL a name we need to reference that here so that's our new URL we now need to create the view called submit too so let's go over to views.py and create that function submit to do here so within this function what we want to do is create a python dictionary that contains an ID and I'm going to hard code this to four for now but we need to create the same structure as we had above for these to-do objects so we need a name and we also need need and is completed field and these are going to come from the front end from the form submission so in order to get that submitted data we need to reference the request. poost attribute in jangle so to get the name of the to-do we need to use the request. poost query dictionary and we're going to get the name attribute from that and the reason this is called name is because it matches what we have here in the input element we gave it a name that was equal to name so we're going to get that now on the server and I'm going to copy this line of code down below we also need to get the is completed field and the name that we had on the form for that was completed so let's copy that and paste it into this do get method so now we have a new to-do dictionary in Python we're going to create a context here and we're going to create a key called to-do in that context and set that equal to the to-do above and finally we're going to for the moment render the index.html template and we're going to return that from this new view now let's test this out it's not going to work at the moment but we're going to test this out and gradually we're going to to fix the issues and make this work now we have this form below the table and the user interface here is not ideal but it's going to do for this video we're going to enter a to-do name and let's enter the to-do of go to restaurant and we're not going to check this but we're going to submit the form and what we get back now is an empty table and we have the form below now why is the table empty the reason for that if we go back to jangle is that we're now returning index.html but that expects a key called to-dos in the context which we are not adding here instead of that we only have a single to-do so we're adding a key called too and therefore the table is empty now instead of returning index.html what I'm going to do is create what's called a template fragment in jangle and you might also see this called a template partial and I have that here on the left hand side it's a file called too. HTML so this is going to be an HTML fragment and if we go back to the documentation for Alpine Ajax we had this example where we had an X Target set to comments what happens and what we want to happen is that when the form is submitted a post request is issued issued to the SL comment endpoint and the element with the ID of comments that list will be replaced with the element that has ID equal to comments and the Ajax response so what we want to do is we want to replace the body of this table that we have here so let's go back up to the table we currently have a table body that contains for each to-do in the to-dos a row but when we submit a new to-do here using this new form that we have we want to add the new to-do to the table so we need to return something that's going to allow us to replace the content of that table with the new to-do or rather than replace we actually want to append the new to-do to the existing table so what we need to do if we want to replace that item is we also need to return a fragment that contains a table body with the same ID so let's copy that table body into a fragment here and we'll close that element off and we're going to create a table row here and because when we submit a to-do it's going to create a single to-do item we don't need any template for Loops or anything like that all we have in the context is a single too too so we just need to render the fields of that to-do in this fragment here so let's create a table data element and we're going to render out the to-do's ID as the First Column and I'm going to copy this down two more times and again we'll reference the to-do's name and also the is completed field so we have a template called too. HTML that encapsulates a single row within the table body and that single row can be used here when we create the new to-do when that form is submitted now we need to change the template that's being return from this jangle view so let's do that now instead of index.html we're going to return to do. HTML now let's go back to our page and try submitting this again when we hit the submit button we get this very basic page back everything else is gone and the entire page has been replaced now why is that happening that's because this is a normal request it's not an Ajax request and the content that's being returned to the page that is all of the content here so now we actually need to introduce the Alpine Ajax plugin and that's going to allow us to send that request and get back this partial here and instead of replacing the entire page we're going to replace only a Target element in the document and we're going to swap the new content in in a particular manner so that it doesn't replace the table rows that are already in the table so let's go back to index.html and this is where we submit the new to do what we're going to do here is add the X Target directive from Alpine Ajax and we're going to set that equal to our to-do table body that we have here so let's copy that and we're going to paste that as the target ID and that means that the response content that's coming back after we submit the form should be swapped into that element on the page and when we add X Target it's also going to change the manner in which the request is sent so rather than a normal request response instead we're going to send an Ajax request from the client and we're not going to reload the page so that's the effect of adding X Target to our form element now let's show that off if we save this page and go back to the browser if we submit the form with the to-do of go to restaurant this time you can see that the table rows have been replaced with our new to-do so that's different we have some interactivity going on now that we've added that X Target directive we have a target of the table body but we can see that the previous contents of that table body have been entirely replaced by the new table rule that's coming back from the server so we have this table row this hyper media coming back from D Jango and it's replacing the entire content of the target element now let's go back to the Alpine Ajax documentation and we're going to learn how to fix this now if we go to to the left hand sidebar there is a directive called X merge so let's have a look at this by default incoming HTML from the server will replace a targeted element and that's what's happening at the moment we have a to-do HTML file that defines a table body with the same ID and that is entirely replacing the existing table body element that we have here so in order to append the new content instead of replacing we can use this x merge directive what we do is we add X merge to a Target targeted element and that will change how it merges the incoming content that's coming back from the response so on the unordered list if we don't want to replace the list what we can do is we can add X merge equals aend so let's copy this directive and go back to our template so the targeted element is the table body here so we can add the X merge onto that and we're going to set it equal to append and let's go back to our page now and let's add go to restaurant in here and submit this and you can see now that the new row is added to the table and it's not replacing the previous rows they are maintained in the table it's just appending the new row to the existing content in that Target element now I can see here that completed is set to none so something's gone wrong there and I think the problem here is if we look and inspect the contents of that field we can see that the value is set to True here now we want this to be a Buon value as you can see in the other rows so let's go back to our jangle view here and instead of pulling out the text of true we're actually going to use a conditional here to check if it's equal to the value of true so if the user checks the check box on the front end this is going to evaluate to true because the value coming through is going to be set to true and the problem that we had here is that when the user doesn't check the checkbox there is no value in the post request for this completed field and it's being set To None on the server because beforehand this completed key did not exist in the dictionary and therefore it was being set To None which is the default value of a dictionary. getet function when the key does not exist so I'm going to try this again let's go back to the page here and we're going to add go to restaurant here and submit this and you can see now we get the value of false and if I add another to-do here and let's say buy a book and we're going to check the completed flag this time that is set to true and each time we submit this form it's going to append the new rule to our existing table body and that's now because we have the X merge property set to append on the target element now let's finish with a quick look at some of the other merge strategies if we go back to the X merge documentation we can go down to this table here now the default as we saw is to replace the target element with the incoming element and we've now also seen append that's going to append the target element's content with the incoming element what we can also do is prepend so let's see an example of that very quickly if we change the merge strategy to prepend and go back to our page and refresh this page let's add go to restaurant and we'll check the completed flag and this time that appears at the very start of the table body's content so when we prepend the incoming data it's going to be added at the very start of the content in that Target element let's go back to the documentation we also have options to insert the new incoming Data before and after the target element and these you might notice are very similar to the HX swap strategies that you can use if you are familiar with HDMX and that's going to be all for this video I want to quickly summarize before we finish what we've done in this video so what we did to start with is create an Alpine JS component and that was created on this div here using the X data directive and then we created a key in that X data called to-dos and we're reading in the Json content that's being returned from jangle for those to-do items once we had the to-dos we were rendering them out in a table here and then we created a form that allows us to add a new to-do and we added the Alpine Ajax X Target directive to that form and that means that when the form is submitted it's going to send a post request to D Jango and the Django server then has a view for that request where we extract the data that's been submitted and create a too and then we return a template partial or a template fragment you might call it to the Alpine Ajax plug-in and the way Alpine Ajax works is it takes the response content and it swaps it into the document at this target ID that's specified in the X Target attribute and if we look at that Target we have the table body here and we have this ID here and we also have an X merge directive from Alpine Ajax at the moment that's set to prepend but we can use other strategies as well and this x merge directive will tell Alpine Ajax how we want to replace the content or swap the content that's coming back from the server into this target element so the Alpine Ajax package allows you to PIR the interactive functionality of Alpine GS with Dynamic content that's returned from the server and this combination allows you to achieve functionality similar to using HTM x with alpine GS but you have the benefit of working entirely with alpine directives and this package Al Ajax it also Builds on top of Alpine and therefore the bundle size is actually very small if you add this to your project now I'm going to go back to the documentation right at the end of this video just to demonstrate this on the left hand side there is a section on comparisons and if we look at the comparison with HTM X you can see at the bottom here that HTM X has 13 kiloby of JavaScript compared to only 3 kilobytes for Alpine Ajax and you can see other comparisons with hotwired turbo and also with libraries like unpol and laravel liveware now if you're interested in more content like this let us know in the comments if you have any other packages like unpo that you would like to see some content on let me know in the comments about that as well but thanks again for watching this video if you've enjoyed it give it a thumbs up and subscribe to the channel and we'll see you in the next video
Info
Channel: BugBytes
Views: 3,601
Rating: undefined out of 5
Keywords:
Id: s7mynG3zxWQ
Channel Id: undefined
Length: 23min 21sec (1401 seconds)
Published: Sat Mar 09 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.