Open BoPeng opened 2 years ago
I've just started using htmx, and found myself wanting to do something very similar, loading content from an inline template rather than a request. After looking through the source it looks like the 'swapping' functionality is deeply embedding within the request code. So I started experimenting with using a temporary URL by creating a Blob and then using URL.createObjectURL along these lines...
htmx.findAll("[hx-template], [data-hx-template]").forEach(el => {
const selector = el.getAttribute('hx-template') || el.getAttribute('data-hx-template');
const template = htmx.find(selector);
const blob = new Blob([template.innerHTML], { type: "text/html" });
const url = URL.createObjectURL(blob);
el.setAttribute('hx-get', url);
htmx.process(el);
});
This looks for any element with hx-template
attribute as in the example above, creating a Blob & URL of the content of the template element, and adding a hx-get
back onto the original element.
I've only tested this with a hx-trigger="load"
though, but I don't see why it should work with any trigger in theory.
I hope this helps anyone else who comes across this thread.
Maybe this could even be implemented as a htmx extension? I've not reached that far into my htmx journey though... I'll post a followup if I manage to do that.
I've published an extension that provides similar functionality in a way that can be handled "seamlessly" through HTMX's extension API - while extensions can't add new verbs without similar "silently convert to a different attribute"-based methods, it's relatively simple for an extension to implement a custom "URL protocol" that it detects and preempts the request.
That said, I do think a proper verb for this as originally proposed would be an excellent idea long-term. An extension like mine is a stopgap rather than an ideal solution, and the ability to bypass making a network request for simple changes is a vital one for many situations.
Have you considered using a service worker to intercept the request and serve the response from the client ?
I've done a few experiments using ServiceWorkers and htmx, it's not the most pleasant or practical of experiences, considering browser support is still inconsistent, ie. some still don't support ES modules for ServiceWorkers!
It's also pretty overkill for the situations where hx-template
referencing a local template is ideal.
From this experience I would only consider ServiceWorkers when an optimization of an htmx request is absolutely necessary, and it can't just be done using a static template and the extension or suggestions above.
But as is always the case, your mileage may vary.
(If anyone is curious, I've got a very simple demo of a ServiceWorker with htmx here: https://jollytoad.deno.dev/calc)
I think this #255 is what we need to have an hx-template
extension without jumping through hoops.
Have you considered using a service worker to intercept the request and serve the response from the client ?
That is essentially the "mock" server that the htmx documentation uses, right? We currently use customized JS code to handle templates in the frontend, I am not quite sure how much a service worker can help.
I think this #255 is what we need to have an
hx-template
extension without jumping through hoops.
While this would be very helpful from a convenience perspective, it's not especially difficult to extract getSwapSpecification
, makeSettleInfo
, and selectAndSwap
from the internal API passed to an extension's init
function, and from there call selectAndSwap
directly. In fact, that's exactly what some earlier prototypes of my extension did.
The real impediment to implementing hx-template
via extension at the moment is that HTMX doesn't process elements which don't have a "verb attribute" (hx-get
et al.), and it's not possible for extensions to modify that list. Trying to work around this limitation results in either
hx-template
attribute into a verb attribute with some sort of dummy URL, which can then be intercepted in the same way my extension intercepts template:templateName
URLs.It's also worth mentioning that it's quite tricky to get HTMX's support for CSS transitions to work properly when utilizing selectAndSwap
directly. My extension gets around that by making sure that only the absolute minimum code - the actual call to xhr.send
that launches the request, and a couple lines around it - is bypassed and needs to be reimplemented. But for a less hacky solution, that wouldn't be an option.
HTMX's process is currently very tightly coupled to the making and sending of an XMLHttpRequest. If it were to be decoupled, to where the request itself is handled via dependency injection, it would be significantly more reasonable to implement these types of features.
I've been coming up to speed on HTMX this month as I contemplate a big web site refactor. As part of that learning, I made an echo web service so that I can really experiment with the client-side semantics without doing custom server-side handlers. Using my echo endpoint and client side template, I created this click to edit demo.
I am trying to implement inline editing for some elements following this click-to-edit example. My form is quite simple so instead of retrieving the form from the server, I am wondering if there can be some way to get the form from the frontend. Conceptually, what I need is
I can implement this in JS or hyperscript, but because
onclick
,render the code
,replace
are all existing mechanisms provided byhx-trigger
,hx-get
, andhx-swap
, it would be nice to be able to create the node from the frontend.I have already been using HTML template so something like the following would work perfectly for me:
Here
hx-template
will simply get the element from the template (or some other elements), optionally replace values of matching elements fromhx-include
orform
elements.Note that I do know the existence of the client-side-template extension. However, that extension allows post-processing JSON data retrieved from
hx-template
and my scenario does not retrieve any data from the server at all. If many of the interactive parts can be pre-loaded as templates, this technique can potentially reduce a lot of unnecessary server requests.