Any way to target local content like <a href="#fragment">Local Link</a> ?
I am exploring htmx a bit and am liking what I see. One thing that I had hoped would work but did not was accessing content in the same page.
With pure HTML you can do a local link using Local Link and I was trying the following htmx code to see if I could do the same with htmx. That does not work however and instead of using the local page it goes out and does a GET request to the same URL as the current page. Can this GET request be avoided somehow?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTMLX Test</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/htmx.min.js"
integrity="sha384-Akqfrbj/HpNVo8k11SXBb6TlBWmXXlYQrCSqEWmyKJe+hDm3Z/B2WVG4smwBkRVm"
crossorigin="anonymous"></script>
</head>
<body>
<div id="#storage">
<div id="#test">Test Test</div>
</div>
<div id="#content">
<button hx-get="#storage" hx-select="#test" hx-swap="outerHTML">Replace this with the content under id=test</button>
</div>
</body>
</html>
I found this extension that had a different behavior in mind for this syntax https://github.com/TheDocTrier/hash-select
But this is not what I am trying to do, I am trying to avoid making requests in some cases.
Can this be done in some way, and would it be a good idea if there were some way to make this work?
Yeah htmx does not have a great option out of the bat sorry as all htmx style requests are always ajax requests. You can create a htmx extension that can probably cover this local select use case. It is often good to use tags to encapsulate content that will be reused later. There is an example here https://demo.htmx.org/ that hosts a test version of htmx with mock-request js library to do this same thing but it is designed really for demonstrating htmx inside jsfiddles where you can not make real external ajax requests. There is some major security risks to consider when allowing possibly unsafe content that the user or malicious party could manipulate to place problem content that could then be abused. Htmx security model is based on the model that the server responses are trusted to include risky scripted content and nothing else is trusted normally.
I think a better idea is to make use of the browsers built in caching support as you can return a partial or full response that has some fairly static content you might want to swap in quickly later. If you set the right cache control headers in your response it will be cached in browser for a period of time and this allows multiple htmx requests with different hx-selects to query parts as required from this cached data which means the browser does all the work for you and you will not be hitting network requests for repeat small patches of static content. You can also use the pre-load htmx extension to improve the caching behavior if required.
Thanks, the mock-requests library looks interesting, I had not considered intercepting the requests that late in the process. If I where to create a htmx extension would you envission that using something like mock-requests to intercept the network calls or would a better design interdict the execution at some other point? I was looking a bit at how to get such an extension working but could not make sense of how to hook myself into the existing code to replace the network call with the results of a function call.
(function() {
let internalAPI = null;
htmx.defineExtension('local-template', {
init: function(api) {
// Called once, receives `api` for internal use
internalAPI = api;
},
onEvent: function(name, evt) {
if (name === "htmx:beforeRequest") {
console.log(evt.detail)
var path = evt.detail.requestConfig?.path;
if (!path) return;
var template = document.getElementById(path);
if (template && template.tagName === "TEMPLATE") {
evt.preventDefault();
var target = evt.detail.target;
const swapSpec = internalAPI.getSwapSpecification(evt.detail.elt)
internalAPI.swap(target, template.innerHTML, swapSpec);
}
}
}
});
})();
yeah I think something like this using htmx:beforeRequest as you can preventDefault to stop the request happening if you detect that it is a local one
Thanks, when I removed the tagName === "TEMPLATE" condition this did what I expected. If removing that is a good idea is a separate discussion. But thanks.
Is there some use to the community to put this in its own github repo for easier linking or should the existence of this discussion in the bug tracker be enough?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTMLX Test</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/htmx.min.js"
integrity="sha384-Akqfrbj/HpNVo8k11SXBb6TlBWmXXlYQrCSqEWmyKJe+hDm3Z/B2WVG4smwBkRVm"
crossorigin="anonymous"></script>
<script>
(function() {
let internalAPI = null;
htmx.defineExtension('local-template', {
init: function(api) {
// Called once, receives `api` for internal use
internalAPI = api;
},
onEvent: function(name, evt) {
if (name === "htmx:beforeRequest") {
console.log(evt.detail)
var path = evt.detail.requestConfig?.path;
if (!path) return;
var template = document.getElementById(path);
if (template) {
evt.preventDefault();
var target = evt.detail.target;
const swapSpec = internalAPI.getSwapSpecification(evt.detail.elt)
internalAPI.swap(target, template.innerHTML, swapSpec);
}
}
}
});
})();
</script>
</head>
<body hx-ext="local-template">
<div id="#storage">
<div id="#test">Test Test</div>
</div>
<div id="#content">
<button hx-get="#storage" hx-select="#test" hx-swap="outerHTML">Replace this with the content under id=test</button>
</div>
<div id="#content">
<button hx-get=".#storage" hx-select="#test" hx-swap="outerHTML">Replace this with the content under id=test</button>
</div>
</body>
</html>