Open dwasyl opened 1 year ago
I'm experiencing this issue as well; using an inner div as a workaround for now but it would be tidier to be able to use the body element.
You could change the default swap style to outerHTML to also swap the body. Or hook to afterSwap and call htmx.process on body.
How are the new classes added to the body?
You could change the default swap style to outerHTML to also swap the body.
I did try this but it wasn't working for me. I'm adding the classes to the body with:
<body
class="application_container
{% block base_class %}{% endblock base_class %}">
With each template having its class in the base_class
block.
It looks like hx-boost ignores all attribute changes to the body, not just the class
tag. It will update based on changes to the contents of the head
tag but completely ignores any change to the body
tag.
You could change the default swap style to outerHTML to also swap the body. Or hook to afterSwap and call htmx.process on body.
Ran into this issue as well. Using outerHTML swap style didn't seem to work, but was able to work around this with an afterSwap event:
document.body.addEventListener('htmx:afterSwap', function(evt) {
const parser = new DOMParser();
const parsedResponse = parser.parseFromString(evt.detail.xhr.response, "text/html");
const bodyAttributes = parsedResponse.getElementsByTagName('body')[0].attributes;
for (const attribute of bodyAttributes) {
evt.detail.target.setAttribute(attribute.name, attribute.value);
}
});
Would be nice to not have to work around this though.
This problem interfered with my use of Alpine, since the page wasn't finding x-data
defined on the body when boosting from another page.
You could change the default swap style to outerHTML to also swap the body. Or hook to afterSwap and call htmx.process on body.
Ran into this issue as well. Using outerHTML swap style didn't seem to work, but was able to work around this with an afterSwap event:
document.body.addEventListener('htmx:afterSwap', function(evt) { const parser = new DOMParser(); const parsedResponse = parser.parseFromString(evt.detail.xhr.response, "text/html"); const bodyAttributes = parsedResponse.getElementsByTagName('body')[0].attributes; for (const attribute of bodyAttributes) { evt.detail.target.setAttribute(attribute.name, attribute.value); } });
Would be nice to not have to work around this though.
I noticed this code updates any element on any htmx-request, and doesn't remove attributes.
Here is an updated version which skips anything that isn't a BODY
tag, and removes all attributes before adding the new ones:
// HX-Boost does not update body attributes nor classes by default.
htmx.on('htmx:afterSwap', function(evt) {
if (evt.detail.target.tagName != "BODY") {
return;
}
const parser = new DOMParser();
const parsedResponse = parser.parseFromString(evt.detail.xhr.response, "text/html");
const bodyAttributes = parsedResponse.getElementsByTagName('body')[0].attributes;
const targetEl = evt.detail.target;
Object.values(targetEl.attributes).forEach(({ name }) =>
targetEl.removeAttribute(name)
);
for (const attribute of bodyAttributes) {
evt.detail.target.setAttribute(attribute.name, attribute.value);
}
});
Using
hx-boost="true"
ignores any new/changedclass=
entries for thebody
tag (whenhx-boost
is on the<body>
tag).Is this the intended behaviour? We have some functionality that depends on body classes, and while we can restructure an inner div to serve the same function, it seems unnecessary as
boost
should merge in the newbody
.I've tested this on
1.9.0
.If this is the intended behaviour perhaps something could be added to the docs.