Skip to content

Instantly share code, notes, and snippets.

@naofumi
Last active December 30, 2024 18:40
Show Gist options
  • Save naofumi/b7953d3d9a08b041bb1b1481e62c11c1 to your computer and use it in GitHub Desktop.
Save naofumi/b7953d3d9a08b041bb1b1481e62c11c1 to your computer and use it in GitHub Desktop.
import {Controller} from "@hotwired/stimulus"
/*
* PermanentAttribute Controller
*
* This prevents Turbo morphing from updating certain attributes on an element.
* It is especially useful if you have changed a class on the browser in response
* to a UI event without sending this change to the server. The server does not
* know about this change and so will send the browser the original class on morphing,
* thereby clearing the state introduced by the original UI event.
*
* Turbo provides the `data-turbo-permanent` attribute to prevent a DOM node from
* being overridden by Turbo (including morphing). However, there may be cases where you
* want Turbo morphing to update the contents of a DOM node, but leave the CSS classes
* as the same. This is common because Stimulus controllers will often change just the CSS classes
* on nodes that were generated on the server, in response to UI events.
* `Data-turbo-permanent` preserves the whole DOM node, so while this will protect the CSS classes
* from being overwritten during morphing, it will also prevent any changes in the content
* from being reflected. This Stimulus controller aims to allow more granular control.
*
* Usage:
*
* The attributes on the node on which the `data-action` is set (the node that receives the
* turbo:before-morph-attribute event), will be preserved.
* Specify the attributes that you want to protect in `data-permanent-attribute-name-value`.
* You can specify multiple attributes separated by spaces.
*
* <div class="[css classes that you want to preserve"
* data-controller="permanent-attribute"
* data-action="turbo:before-morph-attribute->permanent-attribute#protect"
* data-permanent-attribute-name-value="class">
* [content that you want morphing to update]
* </div>
* */
// Connects to data-controller="permanent-attribute"
export default class extends Controller {
static values = {name: String}
connect() {
}
protect(event) {
if (event.currentTarget !== this.element) { return }
if (this.#isProtected(event.detail.attributeName)) {
event.preventDefault()
}
}
#protectedAttributes () {
return this.nameValue.split(' ')
}
#isProtected(attributeName) {
return this.#protectedAttributes().includes(attributeName)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment