Introducing Datastar
So, as you may know, we've covered a lot of Hypermedia content on this channel. We've looked extensively at HTMX as well as AlpineJS and even Hyperscript, but there's a new tool in town and it's called Data Star. We're going to dive in in this video and explore the basics of this.
If you're interested in more content and for example a full-featured application, let me know in the comments. And if you want to support the channel, check out our coffee page. And with that, let's dive in.
What is Datastar? The Core Promise
Now, Data Star, as you can see on GitHub, has 2,200 stars and it's rising fairly quickly. If we scroll down here, I think there's a graph somewhere here. You can see the star history and it almost went exponential here and it seems to be rising pretty quickly.
So, what is the appeal of data star in comparison to something like HTMX? We'll explore that in this video, but let's go to the documentation. What it does is help you build reactive applications with the simplicity of server-side rendering and the power of a full stack single page application framework. And you can use that with any kind of backend as you can see here.
And to get started, it's as easy as adding a single script tag to your HTML code. So, let's copy this and we can go to VS Code and in the head tag of this HTML document, what we're going to do is paste in that script tag. So, we're loading data star from a CDN in order to get started.
Diving Deeper: Core Concepts and Locality of Behavior
Now, we can see more about how to install this if we go to the documentation. So, let's go to this get started page here and we're going to explore this a little bit.
So Datastar is going to bring the functionality provided by libraries like AlpineJS and HTMX together into one cohesive solution. That is the big appeal or one of them. It takes the best things from HTMX but also from AlpineJS and brings them together into this reactive framework and we can manage state and build reactivity into our front end using HTML attributes. So that locality of behavior is present in data star and we can also modify the DOM and the state by sending events from our back end.
Signals, Bundle Size, and Editor Support
Now the installation section here we've already seen this from a CDN, but you can also install it with npm. Now data star is built around these data attributes and these allow you to add reactivity to your front end in a declarative way and also to interact with your back end.
Now there's a concept that data star uses called signals. This is popular in many JavaScript frameworks and it's a way to manage state and you can think of signals as reactive variables that automatically track and propagate changes in expressions. Now, the reason you might want to do this is because if you have a stateful UI, you might want to update certain parts of the user interface when a value changes. Similar to the useState hook in React, this signals mechanism that data star uses is going to give you the ability to do that so that when one value updates, changes can be propagated into the DOM. And you can see we have a VS code extension and also an IntelliJ plug-in and that provides autocompletion for all data attributes.
Now, with all that talking out the way, I want to get started and have a look at data star. And actually, before we do that, I want to highlight one line from the docs. So, let's open this page. And I'm going to highlight this line here. So, at only 12 kilobytes, data star is actually smaller than AlpineJS and HTMX. And yet, it provides the functionality of both of those packages combined. So, that is the big selling point here. It provides the same functionality as HTMX and Alpine together. And it's actually a smaller package than both of those.
Two-Way Data Binding with data-bind and data-text
Now I want to start with this data bind attribute. This gives you a way to set up two-way data binding on an element and it can be placed on any HTML element on which data can be input or choices can be selected from. And examples of these are the ones you would typically find in an HTML form such as input, text area, select, checkbox and radio elements.
So let's build a very small example just to demonstrate this. In the body of this HTML document, let's add an input here and it's going to be of type text. And what we're going to do is we're going to add a data bind attribute and we're going to give it a name of username. Now we don't need a value for this. We can just close off the input element. So we've added data bind username here. What is this doing? If you go back to the documentation, what this does is it creates a new signal. And that signal can be called using the dollar sign and then the name of the variable. In the documentation, they have data bind input. So they can refer to the value of that using dollar input. So if either one of these is changed, the other one is automatically updated. That is the two-way binding.
So let's demonstrate this again by going to the documentation and I'm going to add a paragraph tag here and let's input our name. So we can say my name is and then we're going to add a span here that's going to have a data text property and this is another property from data star and the value for data text is going to be the dollar sign and then username. So we're referring to that signal name of username that we created in the input element. And if we change the input, we're going to see this reflected in the paragraph tag. Let's test this out. I'm going to open index.html. So, we have this unbelievably complex user interface. And what I'm going to do is type my name into this. So, let's type bug bites in here. And you can see that updating immediately on the document.
And what this means is we're using the signal here of username. We create that with the data bind attribute. And that means when the user types into the input, the value of this is going to change. And because we're referencing this signal here, it's also going to update the DOM and it's going to update this span.
So two attributes we've introduced here is data bind and also data text. And what we can also do here is we can use any JavaScript expression inside the data text. For example, if we wanted to convert this to uppercase. JavaScript has a to uppercase function. We can call that. And if we go back to our application this time in the text box, if we type bug bites like that, it is converted to uppercase. So any valid JavaScript expression can be used inside data text.
Understanding DOM Evaluation Order
One other thing to note is that data attributes are evaluated in the order that they appear in the DOM. And what that means is that we can't reference the signal of username unless it has already been declared in the DOM. So if we remove this and place it above the input element that defines the signal, when we save this and go back to the page, notice that nothing is now happening because this is not actually existing in the DOM at the time when we use it. So, let's move the paragraph tag back down and let's continue with this video.
Conditional Rendering with data-show
So, what's the next attribute to look at? We've seen data text. We also want to look at data show. So, I'm going to scroll down here and we have data show. And as you can imagine, this can be used to show or hide an element based on whether an expression evaluates to true or false. So, if you've used AlpineJS, this is very similar to the X show attribute. And if you've used Vue.js, it's very similar to VShow. So, let's see an example and go back to VS Code.
Underneath this paragraph tag, I'm going to add a button. And that button is going to say save. And let's go back to our application. And we can see that button here. Now, let's say we only want to show the button if the username that we have here is greater than a number of characters. For example, two characters. Let's set up a data show attribute on the button for that property. So, data show is going to be set to a JavaScript expression. We're going to reference that username signal. And because it's a string in JavaScript, it's going to have a length property. And that's going to tell us how many characters are in the username. And we're going to set the expression to greater than two. So that means that the button should only be shown if the username that's been typed into this input is greater than two characters.
Let's test that out and refresh the page. And you can see now the button is hidden. We start typing here. As soon as we get to more than two characters, the DOM is updated dynamically. Very nice, very reactive, and very interactive. And it's very simple to use this mechanism. And you might be familiar with that from Alpinejs or other frameworks.
And we can also use more complex expressions. So let's copy this button to the line below. So let's say we only want to show the second button here when the length is greater than two and it's less than five. So we can chain an and expression in JavaScript. And we can refer to username again here and the length property. And we can check that that's less than five. So that is a slightly more complex conditional expression. We can now save this and go back to our application. We don't see any buttons by default. As soon as we type more than two characters, we see both buttons. But one of them is going to disappear as soon as we go beyond four characters.
Dynamic Styling with data-class
So that's the data show attribute. Let's move on to data class. This is another very useful attribute provided by data star. This allows us to add or remove a class from an element based on an expression. So again, there's an expression here. It's going to be a boolean expression and that's going to determine whether a class is shown.
So let's go back to VS Code and inside the head I'm going to define a style tag here with some CSS, very simple class called blue and it's going to set the text color to blue. Now let's say we want to conditionally apply this blue class to one of the elements in the DOM for example this paragraph tag here. Now what I can do then is use this data class attribute and then the name of the class which in our case is blue and the value here is going to be an expression. So again, we're going to refer to that username signal. And we're going to check the length here. And let's just set that to greater than two. If we save this and go back to our application here, we can see the text color is currently normal. But when we start typing and go above two characters, you can see the blue class has been applied.
And of course, we can define any CSS we want here. So let's do something that's not recommended in production applications. Let's define this key frame here to rotate. And then to the blue class, we can add that animation property. And we can refer to our key frame called rotate. And we can define the animation properties as so. So let's save this and go back to the application. And when we start typing in here two characters we have and that is fine. When we go to that third character, you can see the text disappears and starts rotating around the page. This is a nice production effect and I'm sure your clients will love this. Now if we go back to VS Code, let's just remove that because it's not good. And we can remove this key frame as well. So we'll keep the simple color of blue here.
And what if you wanted to add multiple classes to this paragraph tag? So let's say as well as defining the color blue, let me paste in some more CSS here. So we have another class called large and that's going to change the font size. So what happens if we want to apply both of these when the username's length is greater than two or potentially if we want to apply them at different times based on different conditions. So let's show how to do that just now. We're going to remove the blue part of this and we're just going to use the data class attribute and we're going to set this to a JavaScript object. So let's start by defining the object. And this is similar to a dictionary in Python, for example. And then what we're going to have is a key with the class name. So in our case, it's going to be blue. And we're going to map that to a condition. So the blue class will be applied when the username's length is greater than two. And then we can add a comma here. And we can add a second class. And let me move the text to a new line here. And the second class from above was this large class. So let's paste that in there. And we're going to apply that on a different condition. So we're going to take the username again. And we can check that the username is not equal to an empty string.
So we've declared this slightly differently. We're using data class. And then we have a JavaScript object with the keys in that object referring to the class names. And the values refer to the conditions on which the class is going to be shown. So the large class is only going to be shown if the username is not an empty string. And the blue class will be shown as before. So let's save this and go back to the application. And as soon as we type into this field, it's going to increase the font size. And that's because this large class is being applied because the username is no longer empty. And again, if we go back here and continue typing, you can see that when we go by two characters, it changes the text color to blue. And of course, you can also set these expressions to more complex classes as well as classes from Tailwind CSS or Daisy UI or Bootstrap and so on.
Handling User Events with data-on
So that's the data class attribute. Let's move on to another one from the data star documentation. If we scroll down here, I'm going to skip this one and let's scroll down to data on. This might be familiar or at least the behavior will be familiar if you've used the hx on property from HTMX or the x-on attribute from AlpineJS. And essentially, you can attach an event listener to an element and then execute an expression whenever the event is triggered.
So, let's go back to VS Code and let's change this button here. Instead of saving, what we're going to do is we're going to clear the input element that we have here. Basically, we're going to set the username to an empty string when the clear button is clicked. So, let's remove the data show attribute. And this time, we're going to use data on. And after data on, we specify the name of the event, which is going to be the click event. And when the button is clicked, we want to take the username signal, and we want to set that to an empty string.
So, let's save this. And we're going to try this out. If we go back to the application here, we're going to type some text in here. And when we click clear, you can see the input is cleared out. And the reason for that is because we are setting the username to an empty string. So the data on attribute is very simple. It allows you to perform event handling and you can react to events to trigger behavior in the document and so on.
Backend Integration: Architecture and Actions
So that's some of the more useful attributes. I want to now move on to the backend setup. So let's go back to the data star documentation. And if we scroll down here, we are going to get a section on the back end.
Now what data star uses is server sent events in order to stream one or more events from the server to the browser. So if we scroll down here we have code examples in different languages. Here's an example using go. So data star has these SDKs in different languages. In go what you do is you define a new server sent event generator and then you can call a function called merge fragments and that's going to handle merging fragments that are returned from the server into the DOM. Now the ID in this fragment that's returned, this is important because it's going to tell data star on the client side which element to replace based on the ID. and let me know if you'd be interested in an example of this integrating with something like Django or Fast API or any other framework.
Now, if we scroll down here, I'm going to go to some of these backend actions. And here's one of them here. It's the get action to send a get request to an endpoint. So, if we look at this button here, we have a data on click attribute. And the value of that is the get action. And it's going to send a get request to this endpoint. And then the response from that endpoint is essentially what's going to be swapped into the document. So this is simulating some of the stuff that HTMX can do for example by sending a get request to the back end and then receiving a response from that back end and merging that response into the existing document and these get and post actions and so on they are using the fetch API on the browser under the hood.
Showing Loading State with data-indicator
Now if you scroll down further we have some additional attributes for example data indicator. This is very similar to the hx indicator attribute. It's going to set the value of a signal to true while the request is in flight. Otherwise it's going to be false. You can then use that to show loading indicators such as spinners.
So in this example, we have a button. When that button is clicked, it's going to send a get request to that URL. And then we have the data indicator attribute that creates a signal called fetching. And you can see the spinner or the loading thing at the bottom. That's only going to be shown when fetching is set to true. In other words, when the request is in flight. So that all works very seamlessly. And you can use that to show feedback to your users when requests are in flight.
Using Action Plugins: The Clipboard Example
So we saw the concept of actions here. So let's go to the top and I'm going to go to this reference section here and this gives you an overview of different things that data star provides and one of them is these action plugins and you can use these in data star expressions to perform specific actions. Here are actions for all of the HTTP request methods and we have a single browser action as well. This is the clipboard action. So I just want to show an example of this.
So let's go back to VS Code and I'm going to add a final button just below these two. And when that button is clicked, we have the data on click attribute and we use this clipboard action here. And the parameter we provide is the username signal. And what that means is that the value of this signal is going to be copied to the clipboard. So let's test this out and go back to our application. When we refresh the page, I'm going to type bug bites into this. And I'm going to click copy here. And nothing really happens. But if I clear that out and I paste an expression in here, you can see that it has copied that. And we can then paste that in. So that's the clipboard attribute.
The Philosophy of Datastar: Declarative Simplicity
And data star has these different attributes as well that you can use. And there are lots of additional things we can cover here, but I don't want this going on too long. This is just an intro video to data star, a quick overview, and I wanted to present this functionality without setting up any backends. If you're interested in a small project using data star, let me know below in the comments.
And if we go back to the top here and go back to the guide, there is a section on going deeper. And this will give you a bit more intuition on the philosophy of data star. So, it wants to let the browser do what it does best, and that's render HTML while enabling declarative reactivity. And I think this is a good demonstration of why declarative code is really amazing. So, to add a class to an element using the imperative JavaScript code, we have this quite complex. We have to have an if statement, and then we have this expression here, which is pretty complex. With data star, you can do this very declaratively, as you can see here. And it's much more cleaner. And it's also much easier to get a quick understanding of what's going on with this declarative code. And you can read more about signals and the way that data star uses signals in this documentation as well. And you can also create name spaces for your signals too. So you can see that here fu.bar is set to one. So that's the name of the signal. And again, we can dive much deeper into all of this in future videos if you're interested.
And we already saw a little about actions. For example, the backend action functions. And these allow you to send requests between client and server and then perform actions. So if we scroll down to this section here on embracing simplicity, we can finish here. So data star is smaller than alpenjs and htmx, but it does provide the functionality of both libraries combined. So that's quite impressive and I'm interested in doing more content on this. So let me know in the comments if you're interested in that.
Further Learning and Conclusion
And one final thing in the example section, we have all of these different examples of common patterns. For example, infinite scroll, active search, click to load, and so on. We did lots of this stuff with HTMX in the past on this channel. If you're interested in examples with data star, let me know in the comments as well.
And that's going to be about all for this video. So, that's been a very quick introduction to Data Star. If you found it useful, check out our coffee page if you want to support the channel. And don't forget to give it a like and subscribe if you're enjoying this content. Thanks again for watching, and we'll see you in the next video.