About this talk
This talk introduces HTMX, a library that enhances HTML with AJAX capabilities, allowing any HTML element to send HTTP requests and update the DOM without requiring a full page reload. The speaker discusses HTMX's popularity in the JavaScript ecosystem, its small size, and its declarative nature, which uses HTML attributes for specifying behaviors. They explain various features such as support for all HTTP verbs, dynamic forms in Drupal, and out-of-band swaps for background updates. The talk also highlights the ease of integrating HTMX into existing frameworks like Drupal, showcasing its potential to modernize user interactions in web applications.
Full transcript
Okay, we're within a minute of start time and doesn't look like I'm going to make anybody feel late by starting. So, um, let's get to it. Hi, I'm Sean. I am thrilled to see a packed room come talk about HTMX because this is where I've been spending a lot of my creative energy the last year and I'm excited to share with you what we're doing and hope
that many of you will help us make it further down the road. I'm running a thought experiment for myself because I spent all lots of time working with this. Um, and it's a thought experiment about the readability of the markup that's in that we're going to look at. So, I'm curious if you could raise your hand if you've never looked at any HTMX attributes in HTML ever.
Awesome. So, I'm going to get to a point where I'm going to be putting some of that up there and I'm going to ask not going to have no just in your own mind try to figure out looking at it what it does and then I'm going to ask you to raise your hands later if you if you were how close you got. I'm just curious. So,
we're going to talk about background and theory of HTMX so that you understand what it is that we've done in core. So, HTMX is a library that exists in the JavaScript universe. We didn't invent it. This is more of us getting off the island. Um, and it has a very strong reputation in the JavaScript ecosystem. There's a website called Rising Stars where they look at the number
of new stars on GitHub for JavaScript projects. Maybe that's a measurement of what they call framework exhaustion in JavaScript universe because there's they do this every year, but over the last three years, HTMX even once ranked first. It's been in the top five for three years and it's only about four years old. So, um, very strong reputation. It's small. Um, it's smaller than jQuery, which is smaller
than Nex.js in terms of the amount of stuff it lands on the page. Um the it's only 49k minified and um and there's no dependencies. That's it. It's declarative. Let me bump that up. That's not very big, is it? Let's do this. Can I do this? That's not good. possible dim. >> It might be. >> I just need to find my presentations. >> Must be in a
new window. All right, let's try find out. Okay. Am I trying to make your slides go away while you're trying to >> Can't see what I'm talking >> Thank you. like 300% or something. >> I don't know. >> Is that spelled right? I can't read it from here. >> I think it's talk dot right now. It's talk dash. >> All right. How about history? There we go.
That's where we were, right? >> on my laptop I could pinch zoom this but >> try and blast. >> Yeah, that's not doing it either because this is uh revealjs. It's open source. You'll be able to download it, but it's not giving me any control over that. So >> just do your best. Um, so here we have it's declarative, which means that it's controlled by attributes that
are in the HTML. Um, and also I'm going to give you a link to these slides. You can go look at it later if you need if you can't see it from all the way in the back of the room. Any element can issue an HTTP request. The HTMX extends HTML. It completely works in HTML. Normally, we only have a and form that can issue a request.
But with HTMX operating, any element can So here we have a get request going on in this element. Any event can trigger an HTTP request. The native events are supported directly, but you can declare that on whatever event do something. So here we defined a trigger of revealed all the verbs of HTTP. I never really realized this until I started working with HTMX. HTTP is designed to
deliver HTML that they like built in tandem, but HTTP has five verbs. HTML only supports two. get on the a on the a tag and um post on the form tag. The rest of them you can you can write them in, you know, you can use them in Guzzle, you can do all kinds of things where you're doing HTTP directly, but there's no support in HTML, but
HTMX supports all of them. You can target any element in the DOM for replacement. So here's here's the model. Here's the here's the mental construct. Some interaction occurs. You make a request. Select something from the response. Swap that in somewhere after something, before something, in place of something. That's the mental model we're going to be operating with for the rest of this session. that. So, let's go
back and So, um, take a moment for that. Think about the markup that you can see. I'm going to I'm going to try to read it to you for those who can't see it in the So, we're making a request to an export to a form and we're selecting something and we're targeting something and we have a swap attribute. Think about what you think that does just
from what you've heard. So what that does is when this gets triggered, it get it makes a request, it gets some markup, it snips something out using a CSS selector, it targets a CSS selector, and it makes a swap. How many people got close? Okay, about half the room. That's that's really encouraging. Okay, so we did this. So, HTTP HTMX can also call JavaScript. It's less common.
There's only one attribute that does that. But sometimes when something happens, it's not markup we want to do. We want to close a dialogue box. I you know, we have lots of things that we do in in utility JavaScript. You can do that, too. All right, let's look at what we built. So, the Ajax system processes for you uh CSS and JavaScript, the current the existing Ajax
system. We don't want to lose that. Now, if you're not if you haven't spent any time with the Ajax system, this means that when you make a request for a thing, and the the the thing you're requesting adds a new library, you you need that that CSS to come in for your stuff to look right or you need that JavaScript to come in for what you for
it to work, right? But you don't want to take everything from the page that's coming in because then you'll have double CSS and trying to load it be a mess. The people before us put something into the system that keeps track of what's on the page, communicates that back to Drupal, does a diff, and only adds to the response the things that you need. That was already
there. I didn't build that, but it but it was there in anticipation of maybe we'll build something else someday. And so that works. We have code that makes that work. And also uh when the if the stuff that you import is HTMX powered um we we attach all the things that are supposed to be attached to make that work also. And if you download these slides later
and you want to go look at the code that makes that happen, um here's here's a reference to the processor and core that We have a factory object for HTMX headers and attributes. You have two control surfaces in HTMX. Mostly it's about HTML attributes that get put on the element. There's also some headers that you can send back with your response that make things happen. So we
have a new class called HTMX. Every method in HTMX, every attribute has a method in this factory class. It's essentially an attribute maker where you're going to call a method on the HTMX object to give it the information that need to go in the attribute and it's going to end up in your render array. We also have a method for every HTMX response header. the doc blocks
on each of those methods have links back to the HTMX documentation. And of course, if you're using an IDE that autofills for you, as soon as you instantiate this object and you you do your arrow or whatever, you're going to start to get all the methods that are available to you. So, you don't have to have this whole map in your head of what all the HTMX
attributes are or what the response headers are. They're going to be available to you right away. There's another object in core that we modeled this on. It's cachable metadata. This is the object that you can use to collect cache data about other things in Drupal and then you can apply it to a render array and all the pound cache properties that you're supposed to have get applied
to your render array. So we're using the same pattern. Similarly, we have a static method where you can take a render array and ingest it into the factory. So then if you wanted to replace something, you could just call that method again because there's there can only be one attribute in on an element. So if you call the swap method a second time, it just replaces whatever
was already in swap. So here's an instantiation of that. This syntax has been around in PHP since I think 5.4. I really never used it till I started using this doing this work. But this is simply a factory method. So you you can say like dollar sign htmx equals new htmx and then work with with the variable. But you're going to immediately throw that away. So this
syntax is puts parentheses around the call to new which your your object is temporary. You're holding on to it. You're going to call the methods that you need to instantiate the different attributes and the last thing you're going to do is apply it to the section to your render array. Now, if you put a breakpoint in here and look at it after that, you're going to see
a pound attributes and all of your attributes are going to be there or you're going to see the the the attachment section with the with the HTTP header. It'll all be done for you. But you don't have to remember how to do any of that. All you have to do is instantiate the HTMX factory, call the methods to create your attributes, and then apply it to the
render array where this needs to go. We support dynamic forms using HTMX. There's a little snippet here from the form builder. The when you build a form in Drupal, there's a there's an ID that attaches that particular instance of that form to the cached version of that form. And when the values update, like when you submit it back with values and you get a new build to
that form, you have to update that ID in the markup or you your values don't get maintained. This we have some code that detects in the form builder if the request that's coming in is coming in as ht as an HTMX request. If it is, we do this. And what's happening here is we're putting what's an attribute from HTMX called swap out ofbounds which piggybacks on whatever
else is happening. An outofband swap in HTMX is whatever else you're doing to request a thing and then get a thing and then put a thing also swap So when the form comes back whatever else you've done this outofband swap will just replace the form ID in your It's a clever bit bit of programming from Theodore um the front-end maintainer that those are all the lines of
code that it took to make the form builder support dynamic forms with HTMX. You can go see it in the full logic. There's a citation for if you look at my slides later. We also have um a trait that you can use to identify what was involved in the request. I'll talk about why that's going to be useful for you in a minute. There's a reference to
it. It's already included in formbbase. We're using this trait. Um what? this trait has um a method for every header that HTMX sends back to Drupal. When you make an HTMX request, HTMX puts a lot of helpful information in headers that come along with the request. Things that are helpful to know like which element triggered the request, what thing are you targeting? and so on and so
forth. So every header here is supported in this trait all the way down. They're all available. There's one abstract method in this trait which is get request in your class that you include this in. You need to implement that method. Um, those of us who are working towards type safety in in PHP may notice there's no um there's no return type on that method. That's because forbase
has this this method already. But it doesn't have but it's not up to speed on returning types. So we couldn't put one here because then we would have had to put a type on the method in formbbase and then we would have broke broken all of your formbbased implementations and that would have been an API break. We couldn't do that. So that's Drupal development for core. But
that's that's but this is really useful because the thought paradigm is completely different from the Ajax API. How many people have built something with the Ajax API in Drupal? Oh wow. Mo more people than have looked at this is great. So in Ajax API you have to write a callback that's going to that's going to create the little snippet that you send back. We're not doing that.
es especially with w with with with forms, you're rebuilding the form. So rather than having logic that's that that doesn't affect the normal form build, you have to think about how am I going to build this form with user input if you're building something a dynamic form. And um and so one of your questions is going to be when you're building that logic, well what triggered the
form rebuild? Was it the first select or was it the second or was it a checkbox? Whatever you're doing, you need to know that so you can react to that. So, this this is the trait that's going to help you do that. We'll look at some examples when we get to the the examples. Another thing you'd like to do to make it more efficient. I'm we're sending
back HTML. HTML is the data format for HTMX. And I want to send back as little as possible. I want to build for you in the rendering process as little as possible. Right? I'm doing a form. That was our that's our primary example we're going to look at in detail today. I don't want to build the menus. Okay? I don't want to look at the menus from
cache. I don't want to build the blocks. You have a dynamic block that does a bunch of expensive stuff. I don't want to build that. So, what I want is just the thing. And if you're building a custom endpoint that really is returning a fragment, then you really even want that even more. So we have we have ways of returning only the main content section of the
page. You can do that on a per request basis by using the only the main content method on the on the factory. Um, this re le leverages something else that our predecessors um, mothers and fathers in Drupal created for us. It's called wrapper format. And here's the problem that it solves which I kind of knew about but hadn't really thought about till we started actually building this.
You can't send back two different kinds of HTML responses on the same route without having something in the URL to indicate that because of caching. Like if you ask for node 27 and all I send back is main content and then somebody loads node 27 as a page, it's going to be messed up, right? The wrapper format is a query parameter that goes on the end of
the URL and that communicates to Drupal that it should do something different and return a different response. We're already doing that in the Ajax system. Um uh there are some other instances in Drupal core where that's done. We've added a wrapper format string that triggers the HTMX response renderer and that renderer renders the system messages and the main content and that's it. Maybe you're building a special
endpoint like maybe you're building a thing that's designed to return fragments. You can put an underscore HTMX route option in your route definition and it doesn't matter whether people ask for main content on their request or not. It's always going to use that that special renderer. Those are the tools of the tool set. I'm going to go into examples in a moment. Um, but I'm two minutes
ahead of my timeline. So, anybody have any questions at this point? >> Yes. >> Speaking about caching, if your form builder is changing what it's doing based on custom HTTP headers. Is that something we're all going to have to write into our our VCL? >> Um, you you need to allow those headers through. Yes, if you're >> c by the value of those headers change the output.
>> Yes, I suppose you might need to c. So the question was, do we need to do we need to account in varnish for requests coming in with HTMX headers and adjust our caching based upon that? That's a really good question. Probably um but um the header is only going to tell you what triggered the result the quest the I think you're just probably going to want
to let that through because you don't know what value the user put on the form. So just because I I I I toggle a to select there could be 27 different responses or 100 responses that could come back. So I wouldn't necessarily cache based on >> So is it safer to sort of like we do today uh return pipe or or pass for posts and other things
that aren't safe to cache. If we see HTMX headers, are we going to also just want to not cave a hit from pass or something? I don't entirely know the answer to that question because we're probably going to be based on experience. But if it's a form, it's coming in as post anyway. we have we don't we don't have put and delete, right, in our routing because
we don't because all we do is is post and get. But this gives us the opportunity, for example, to make a delete request when deleting a node. Interesting idea. Um, any other questions? Yeah, >> you talked about the out of bounds. >> Yes. Swap. >> So, um, with the with the main swap, you can only have one of them on your response, but with the out of
bounds, can you have multiple? >> You can. If you went if you went to Pierre's session this morning on display builder, brilliant architecture. All of his islands come through as divs with a swapo OB on them. So if he's updating 12 things on the page, he returns 12 swap OBS and they all update. >> It's out of band, right? >> Out of band. Yeah. >> Banned. >>
Yeah. Out of band. OB. Any other questions? We're still ahead of time. Yeah. >> Since we're swapping things on page, how does that how does accessibility play into that? Um, if you're swapping things that um that are announcable, we're probably going to need to put it in a live area. Um, I don't I'm not I'm a primarily a PHP developer. Um, so I don't know what happens
in a normal Ajax request when you replace something on the page. Um, but it's the same the answer is g whatever that answer is is the same answer because we're just doing Ajax. We're just we're we're able to do Ajax. with just writing some some a some attributes in our we're able to put on event listeners with just adding some attributes but under the hood it's still
JavaScript manipulating the DOM. So whatever for those of you who are better JavaScript developers than I am and know accessibility whatever the answer is that's the answer. >> So Drupal announce there's a call for that Drupal announce the area live announcements. So there there is a there is a there is a command for that. Yeah. >> Um an an Ajax command um that >> we we haven't
replaced that yet. Um but my understanding from the little bit of understanding I have about how accessibility works with this sort of thing is if you put an AR live like we do on the system messages and the the reader specifically looks for updates in that section. I don't know what happens outside of that. Another question in the >> think about delete. >> So right now deleting
a node would be a route and then the route have the node ID in item if we switch to uh the http delete or then is it just sort of like a technical change or does it >> it'd be a huge change. The question is what could we actually do a delete route on nodes? Um so you can put the method in in the routing system. Um,
so you can have two different kinds of HTTP verbs on the same route in our routing system. Um, we don't do that because we don't do that, but it's there. Um, all right. So, let's look at some examples. We're going to look at the config single export form. So, I think I have this in another tab. I do. Um this is this form and most of us
as Drupal developers have been here before. Um this is in config synchronization export single. Um let's remind ourselves how this form works. You pick a thing here on the type and this select updates with the kinds of things that are on that are available and then you pick the thing and you pick it and the text area gets the YAML, right? This is our test case. This
is the only instance of HTMX in Drupal Core 11.3. No, but it's there. We picked it because it's complicated and simple at the same time. The first select controls the value of the second select. The value of the second select causes a an HTML replacement on the third item. right. With me. All right. Let's go. Let's see what we can find. Where's my thing? So, you have
dynamic selects. Here are the two selects. Um, they're both they're both doing a post back to the form. Um, and they're both only want main content. They're both selecting something and they're targeting some another CS CSS selector. In this case, they're both the same because you want to get the old you want to get the new select value out of the request. You want to put it
in place of the of the select that's already on the page. Um, and um, and they're both using the same swap strategy, which is outer HTML. Swap the whole thing. The last thing you see there in the in the markup um ignore title equals true. Now HTMX has a design assumption that if you're making a request and replacing something on the page, you probably want to update
the title of the page because you've done something. We don't want to do that. You might be requesting something that you that's just a little snippet. You can do that. There's you can set that to true in the in the method call if that's what you need, but most of the time we just want to get the snippet. So here's the form. I realize that everybody can't
see the markup this even though it's the full screen. So I'm just going to talk through some of the principles, but you can go look at this form in on my slide or you can look up in your codebase. Before each of these selects had an Ajax callback that had the logic for for calculating what should be in that thing. I was able to keep most of
that, but I had to adjust it to to be able to rather than being passed some data, look at the parameter that was coming in, figure out what the value that the user had chosen and then and then calculate the the right configuration, the right options for that select. There's a great Easter egg here though I found look working in this um see where's the form method?
There it is. Notice on the build form method there's two string parameters at the end of that method instantiation config type and config name equal empty string. That was never used. We never we weren't using that in Drupal prior to 11.3. It was there, but it enables a cool thing that we're able to I don't know if you can see this in the browser, but notice that
I have that the that the URL in the form has updated. We're doing that with HTMX. So every you pick one of these, now there's one parameter up there and you you pick the second one and the URL is automatically updating every time you change something. We can do that in the a in the Ajax API. Um but you have to construct a command and send it
back. Um I've got one parameter in the markup. I'm sending back a push URL header that's changing changing the value. And that means you can configure this form and um take the URL and send it off to somebody. Um I hadn't noticed that behavior in the form. Um, my colleague Jake Rockwitz is over here and we were talking about this update at the time and Jake said,
'You know, if you did that, you'd be able to do this thing and it's just really fun to go change the select mark and watch the URL change and realize it was one line of code. That's all I just call the method. One let's go over here. Any questions about how how we how what we did with that form? I could go bring that code back or
>> I'd be curious I'd be curious to see what you just talked about. What what that one line you're pushing and also where are you where are you doing anything with HTMX in the form build >> Okay. Um I'm going to bring this up. I can't see it from here, but when I get over there I'll be able to see it. Um Okay. So line line 98
on this code listing. Um I get the URL. You need a URL. Our methods expect a URL object. So we can do con um caching capture. Um and um and then I'm um I'm posting to that form You can almost see that from here. So I'm saying only main content. I'm saying the CSS selector I want to select. I'm saying that the the CSS selector I want
to target. I'm specifying the swap strategy which is And then I'm applying it. >> And that used to be the Ajax render array in that section of it. >> In that in that section of it, yes. Um, if you had looked at this before in setting up the render array, there would have been an Ajax property and there was a call back. Um, and the callback just
sent back the and the post the push URL. Somebody who's closer to the screen when you see a push called the push URL is that right here. >> Line 142. You can see you can see in 142 I get I get the updated URL and then I use I add it on to the form. Is that right there? Yeah. So we do that when in the logic.
So you have to think of the the brain change is thinking about when do things need to change. So when do you need to update the URL? either you need to update the URL when one of the selects change. And so, um, when one of the selects change, we add this on to what's coming Any other questions at this point? Yes, sir. It looks like um when
the config type is changed only the config name is reloaded not the doesn't clear out the uh the YAML. >> Um that that's a great uh use of swap OB >> That's what I was going to ask. >> Yeah. So um the the in the logic for the for the text the question was you're for the recording you change the the type and it changes the name
but it doesn't look like it's changing anything with the with the input um when when the form if the form rebuilds and all you have is the config name the config type so config name is empty automatically in building the form the text area should be empty. So we just send that back as a swap OB. When whenever the config name changes, we put a swap OB
property on on the text area. And this is where we get into the style and art of programming. You could conceivably just make the config text area always a swap OB because when anything changes, you're probably going to update it. I decided not to do this in this first example because I really wanted to see to show you over and over again the paradigm of make a
request, get a thing, pick where it goes, replace it. So, this gave me the chance to do it here twice. Um, we we had a conversation about that in the development of it. The swapo OB is a little magical and I wanted to I want to make it as unmagical as possible. But if you look through the code, you can see where I'm either there's a point
where I just I look to see if the config type changes and if it does, I put a swap OB property Okay. Token browser. Um uh Andy Marquee, maintainer of custom field module has been active in our Q and he said, "You know what? I think the token thing could be better with this." How many people have used the token picker? And you know there's a recursion
limit of three levels. Yeah. Um that's because it's it gets built all at once. And if you can't you have to put a limit on it if you're going to build it all at once. Um Andy did a thing where he built a replacement token token browser contrib module that just replaces the token browser um using HTMX. And if you're if you're making a request, you can
dig down a tree as far as you want. Now, completely makes that more usable. So, here's his example. It's in a table and this I I highlighted here because he's doing an he's taking advantage of a very cool HTMX property. Many times these attributes are inheritable. So all the rows in the token browser the thing that wants to select is the same idea. So he just puts
that up as the top at the top of the of the of the table and that gets inherited by all the all the elements using HTML inheritance kind of a thing. It's just HTML working the way you think it should. So that's token browser PR session this morning on display builder. The whole thing runs on HTMX. It wouldn't work without HTMX. It's designed with HTMX in mind.
And uh it is a competitor from what I saw in this morning's presentation, a real and honest competitor with Canvas um with a fraction of the page weight thanks to Um the yesterday in the Greece note the the new capabilities of ECA were highlighted and that little lightning bolt thing that was demonstrated where you click on it and a little form pops up and you fill it
in and you click it. That's it. That's powered by HTMX requesting the form, clicking it, posting it back. Um if you went to Jurgen's talk, the the little um event thing he's got down in the corner, same thing. There are places where that doesn't make sense because it's so complicated and he's using React Flow. So, we're not in competition with SPA paradigms, but don't do that unless
the thing you're doing is so complicated you actually need it. The founder of HTMX says, "Look, if you're building Google Sheets, of course, you need that. You can't do a thousand requests. The thing will die. But for making one request, you can use HTMX." Okay. So I want to build something with you to get to so illustrate this paradigm. Um so problem statement dynamically insert the login
form so that the user can log in without lo without loading a new page. Clear? Okay. So, we want um fun fact, you can use the HTML tag render array property to get a button tag um in Drupal. But if you use the button property, you don't get a button. Maybe we should have a button. Um but you get an input. That's what this is. Um so
you need to make a request, you need to get a thing, you need to put it somewhere, and you need to swap a thing. We're going to walk through those decisions. So, you need to get a thing. We're talking about slash user login. How do you find out where that lives? Search your codebase for slash user login. You'll find this router entry. I like to build my
URLs from route name from route definitions. They're just conceptually easier for me. So, that's user.lo. I need to know that, right? And look at the source page. Where do you want the thing to go or what is it you want to select? So you go to SL users login inspect source. Here's a form. It's got an ID. I need to know the CSS selector. So that's up
here. Yes, IDs are semi- dynamic in Drupal. No, you're not going to get two copies of this form on the same page. So I'm going to use the ID. Now, where's it going to go? I want to put it um in the default Drupal installation up in the header where the lo where the user menu normally goes and there's a login link. Um so I look at
the markup and I decided based upon the how the CSS is by default, it kind of looked broken when I replaced the login button when I was messing around with this. So I decided to put it at the end. So I'm going to this is my target and I'm going to use an afterend swap strategy. something custom designed in HTMX, which means what it says it does.
Put it after the end. Okay. So, where can you get it? What's the CSS selector of the thing that you want? you're going to target? And what's your swap strategy? Those are your basic design questions. So, I built the render array. I used a block for this because it was easy. I put those design decisions into the definition of my HTML uh property. applied that to to
the um to the the render array. I put in a second option for a link to log out. I used access controls for Drupal to decide which one's displayable. Questions at this point? Okay, great. So, let's come back over to my example site. Let's log out. Okay, so there's our button. >> We probably would never. Now that's not done from a UX standpoint. But the point with
this demo, the point of the point of this demo is in that much work, I built I added dynamic interaction to a Drupal page. Imagine what we can do in our admin UI. How app-like could the could admin become in Drupal? How many times have you heard, well, this is cool, but the admin UI is so 1995 or what, you know, 2000 or whatever. Um, shouldn't we
just rebuild the whole thing in React? Um, I say no, because we can just do this. So we have an initiative to take all of the Ajax API implementation and core and replace it and in the process build a handbook for if you used to do this. This is how you my lead collaborators, um, Teddor, Nathaniel, also known as Catch, me, and Pierre. those are the four
people that got it in Now, I need you because there's um 40ome instances of of Ajax command like different kinds of Ajax command instances across Drupal We need to look at those and say, should we replace that? If we're going to replace that, how would you do that with HTMX? So, we have a cookbook or a what do they call it? A a guide in documentation. We
have a page for each of those. We have a link documentation issue for each for each Ajax command. And it's a it's an experiment. It's a research project. It's it's doing what we like doing where you play with some new technology and figure out how you can make it do a thing. We need to do that for every Ajax command and document it. And we're going to
do that by going through um the the usage of Ajax and core in usage order. So no surprise the biggest usage is um methodology pound Ajax with a wrapper key gives the thing you need that you're going to replace what you're making with. So that that's just a special instance of replace command and that's the second most common usage and the third most common usage in core
is the HTML command where you want to insert some other HTML. Well those are all like right up our alley. we should those we those we can figure out pretty easily. There are other things that we need to figure out like how how to bring the messages in in a in a in a controlled way and maybe solve the problem of messages not being able to be
themed without writing a JavaScript thing um for Ajax anymore. But those three things we have issues we have met planning issues um for created them today. Um they describe all of the different places in core where those things are going on. We need people to uh make an issue for replacing one of those, figure out how to rewrite that that PHP with this new thought process in
mind to return the right thing and just help us refactor core. So that's the work. That's where we are. Um you can join the HTMX channel in Drupal Slack. U you can do the research I'm talking about. I'm flying home tonight, but you can find other collaborators in the contribution room tomorrow. those issues now exist. Um, and we can get it done. So, I put reference links
in the slide. Um, here's a QR code to the GitHub repository where this where this presentation lives. Here's a QR code to the session uh evaluation form. Please fill out a session evaluation. Most of all, if you got if if this got you excited at all, come join the HTMX channel. Let's help me help me get it done. Thank you. Any questions? >> Is the idea to
like rework how the existing replace? >> Good question. So, the question was, is it is this rethinking how the existing replace command works or is this coming up with how to do it in HTMX? It's the second thing. Our goal is to deprecate all instances of command interface, deprecate the Ajax renderer, the Ajax response. We want to take all of that out because we don't need to
be responsible for maintaining any of that anymore because HTMX can do all those things. >> Yes. Over here. >> Yeah. You >> I pile on to what you're saying about uh the potential here because we're making more dynamic back end the admin interface because because it's so easy to implement the barrier to entry is so much lower like creating a dynamic form when writing your own Ajax
plugin like prevented a lot of people from attempting it. >> Thank you. Yes. So for the recording I'm pointing out that the this has lowered the bar to entry which increases the possibility that somebody could make a could actually use Ajax in Drupal. So if I have an idea to about our website to like make it more personalized personable let's see if there's a button can trigger
um can trigger like different brand color or you know like different like which color you choose for the homepage. Let's see >> red, yellow, blue, whatever. >> So can you talk about like what's the like So what's if you do it? I mean this definitely sounds like HTML X. Okay, do >> So So here's a thought experiment use case. I have a button that I want to
use to change the color of something. Um I can come up with two ideas spring to mind. One JavaScripty, one HTMLy. Um JavaScript the HTML thing is um I click this thing, I make a request, the button gets replaced with a different class. the CSS already exists to change it from blue to yellow and it's yellow. Um uh you could on click using HTMX on call a
JavaScript function to do the thing. This particular thing I think is pretty easy to replace the the HTML and change a class but two ways to do it. >> I'm just curious, are you going to be at the contribution event tomorrow? >> I'm personally not at the contribution event tomorrow because I have to get back to New York. Um u but um Urggon's here over here um
he's built some stuff with HTMX. Pierre isn't here but he'll be around. Um uh but literally uh if you if you go to the pound htmx channel on Drupal Slack, there's a link to our meta issue. Uh tomorrow happens to be our every twoe coordination meeting. Uh I'm going to be posting these issues in that Slack channel. Um, and it's literally go find a method, figure out
how to do it, write it up like a change record. >> You Yes. >> Can you swap body classes without having to shift the entire body element? >> No. >> There's other um there's something called AlpineJS, which is like an attribute based interactive methodology. So you would use something like that to make a button that something on the page because HTMX is all about HTTP calls. >>
Yeah. So, so the data format is HTML and if you're going to change the HTML of the body tag, you're changing the whole >> Otherwise, you're just going to do >> right? >> On click. >> Yep. >> But you don't have to write your own event listener. You can do you can do hx on event name call a function >> using the htmx, >> right? And the
no event listener, >> right? You didn't have to but you still have to write the JavaScript functions. No swap strategy, right? Swapping, >> right? Because hx on creates an event listener on the thing >> on the particular event with HTMX >> and a little bit of JavaScript. >> Little bit of JavaScript. >> Yes, sir. >> So, so canvas uses React then this is all HTML display. So,
what are your thoughts on canvas in general? I don't have it I don't have an informed opinion because I haven't looked I haven't spent any time with the code or played with it in my browser. Um so my uninformed opinion this question is what's going on complex enough that it needs an SPA framework? I I have a complexity filter on all my engineering. Um and is is
what you're getting worth the complexity? I'm sure my colleagues get tired of me asking that question, but I ask it all the time. >> Seems to be less complex. >> Well, Pierre demonstrated really well this morning building a display builder without it. >> Um, so I'll leave that session to answer that question. It'll be recorded if you didn't c catch it. >> I don't I haven't spent
any time with it in that space. >> I have tried hx inside a canvas in a code component and it didn't work. So, so our code if you put if you if you if if behaviors are being called like the normal sort of the norm the the normal sort of you things that happen when a then it'll get instantiated it'll because canvas is just building the display
it's not rendering for the end user right yeah >> yeah so do you have a good example that currently a website using Drupal that using also using ATMX. >> Well, my my primary example is that form that I showed um because that's what we've done. Um I have a small admin interface I built when I knew less. So, caveat, I knew less. Then, um in the HTMX
contrib module, I have an off-campus dialogue thing that slides in and out and and and and loads a bunch of of blocks and then updates the the the list on the other part of the page when you pick a new thing. I think I mostly would do it the same way today, but not entirely. Um, but that's another >> Token browser. >> Token browser. Yeah, >> that
was a problem. How do we render all of the tokens in this one UI >> in the back? >> Yeah, I have a question. I able to cut off some elements of the form, remove elements from the reform and how form state is val for. So what you have to think about is and you rebuild the form. So if you're going if you're going to if if
you're going to change multiple elements being present in the form, >> your replacement tag is probably the >> Uh replacement back as usual replace. >> So So if you technically if you if you returned the if you returned the things that you wanted to change or delete in a swap OB, we're going to change the form ID. that's going to take care of the caching for you.
I mean, you could probably do it in fragments. But in in Ajax API, we we thought about changing only the one thing and we really hyperfocused on calculating the new markup and that was it. And I think you we have to change our thinking to say, well, I'm building the form. I'm building the form with these values in mind. So, how does the form state change? And
then get the form. Or if you're doing a multi-step form, I'm taking these values, I'm building a new form with those ideas in mind, and then I'm replacing the form. >> If you if you have a very large form like think somebody built a giant web form, it's three or four >> and you do have to replace the whole thing. Is there any sort of like reconciliation
thing so you're not like losing scroll position down the page or >> is that the browser kind of handled. >> That's a that's a great question. Um, built into HTMX, you can there's a property that you can set that you can scroll to the thing that you replaced. >> Um, I I have a I have a mini pager in the contrib module because I wanted to experiment
with that for views that implements the pager in HTMX. Um, and and there I use that property to get back to the top of the view. Although if you're replacing the whole form, would it scroll back to the top of the form when you replace the way at the bottom or you can like scroll to the target of >> you scroll to the target of the thing
you replaced? >> Um I presume that there is a Drupal library that wraps HTMX or you have to explicitly attach that. Is that part of >> Not if you use my bu Not if you use my >> Yep. Um, and then the the the question was is there how do you get the implementing libraries into your markup for the recording? Um, if you use the factory, we
add that for you. Um, there's a technical answer is there's a there's a Drupal HTMX library that is our custom JavaScript to do the asset kind of, you know, the stuff that we need to do Drupaly and that requires the um the core HTMX library which is actually the HTMX library. >> Yes, ma'am. um works with rearch say for example use click and your code you want
before you actually solve the backend process the you want to do some type of inspection does it work well for >> okay so um repeat the question for the recording but also for my own understanding um something's triggering an htmx request you want to do something before the request goes, you want to inspect it and maybe react to what people are asking for. >> Yeah. So, for
example, you have a form and there's certain conditions that has to be met before that request can go back to the backend system. So, you have them for an event listener that says if it's clicked for this particular button, element, whatever you're using, do these checks. >> Sure. So, um HTMX is well architected with a bunch of events. um that fire as it goes through its process.
You could add an event listener to any of those events. Um specifically, there's a config request event that we're using and where we add some more things to the request like Ajax page state. Um but um there's a there's a there's a robust event system, JavaScript event system. You could put a listener on any of them. Um you could u you can even use the Ajax a
the HTMX API has a very small API to do that without you can call the HTMX object and call and call on and you don't even have to write your event listener. Um and um in our contrib module there's a there's a subm module called htmx debug which when you enable it you'll see all those events in the console. I assume like Drupal attached behaviors runs again
once. >> Yes, Drupal Drupal. The question is Drupal attached behaviors. We run Drupal attached behaviors on all HTMX insertions. Um and if you do an Ajax insertion, we run a we run um HTMX process so that your the HTMX stuff works too. All right, I don't see any hands. Thank you for coming.