htmx
htmx copied to clipboard
[proposal] extend hx-preserve functionality to optionally preserve attibutes and classes only
When updating elements on the frontend sometimes we just want to update the data and keep some frontend specific classes/attributes unchanged. Some elements might be highlighted, hidden, or expanded on the frontend and when the update is received we want to preserve classes and attributes that are responsible for this (eg. <div hidden> , <div class="highligted">, <details open>, ...)
hx-preserve currently only supports the preservation of the whole element which means that it can not be used if we want to update the data. We can however extend its functionality by accepting parameters in a following manner:
hx-preserve="attr:open" and hx-preserve="class:hidden" This way we can preserve specific attributes or classes.
implementation seems quite simple:
` function handlePreservedElements(fragment) {
forEach(findAll(fragment, '[hx-preserve], [data-hx-preserve]'), function (preservedElt) {
var id = getAttributeValue(preservedElt, "id");
var oldElt = getDocument().getElementById(id);
if (oldElt == null){
return
}
var parameters = getAttributeValue(preservedElt, 'hx-preserve')
if (parameters){
preserveAttributesAndClasses(oldElt, preservedElt, parameters)
} else {
preservedElt.parentNode.replaceChild(oldElt, preservedElt);
}
});
}
function preserveAttributesAndClasses(oldElt, preservedElt, parameters){
forEach(parameters.split(","), function (parameter){
{
var splitted_parameter = parameter.split(":")
var qualifier = splitted_parameter[0]
var name = splitted_parameter[1]
if (qualifier === 'attr') {
if (oldElt.hasAttribute(name)) {
preservedElt.setAttribute(name, oldElt.getAttribute(name))
} else {
preservedElt.removeAttribute(name)
}
} else if (qualifier === 'class') {
if (oldElt.classList.contains(name)) {
preservedElt.classList.add(name)
} else {
preservedElt.classList.remove(name)
}
}
}
})
}
Wouldn't you be able to use inner swaps when necessary?
Is there a case you can show when it's not possible to work with inner/outer swaps? I'm curious what I'm missing.
You can have a list of items that gets updated with a single request and therefore swapped simultaneously.
<div hx-get="/accounts"
hx-trigger="every 10s"
hx-swap="outerHTML">
<details id="1">
<summary>summary1</summary>
details1
</details>
<details id="2" open="">
<summary>summary2</summary>
details2
</details>
</div>
related reddit thread: https://www.reddit.com/r/htmx/comments/196do20/periodically_refresh_a_list_of_items_with_htmx/
I agree with @kizmonavt that it would be a useful feature.