Last active
March 31, 2021 23:04
-
-
Save xtr3me/cf99f6673ebcca83f111abd41e9676bb to your computer and use it in GitHub Desktop.
Workaround for hotwired/turbo#186
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// I use Rails and my Stimulus controllers are available in application.controllers. | |
// This adds a listener that is triggered when the turbo:before-cache event is emitted | |
document.addEventListener('turbo:before-cache', function () { | |
application.controllers.forEach(function (controller) { | |
try { | |
if (typeof controller.disconnect === 'function') { | |
controller.disconnect() | |
} | |
} catch (_) {} | |
}) | |
}) | |
// Alternative: Add this in the connect function of the stimulus controller. | |
document.addEventListener('turbo:before-cache', function () { | |
this.disconnect(); | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- wrap your script tags in an element that includes the workaround controller --> | |
<div data-controller='turbo-issue-186-workaround'> | |
<script>console.warn('Executed by the workaround stimulus controller');</script> | |
</div> | |
<script>console.warn('Will not be executed...')</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Controller } from "stimulus" | |
export default class extends Controller { | |
connect() { | |
// Could be replaced by requestAnimationFrame() | |
setTimeout(() => { | |
[...this.element.children].map(el => this.activateScript(el)); | |
}, 300); | |
} | |
// Trigger this method to remove the script elements when the turbo:before-cache event is emitted | |
// Add additional logic if you need to unmount your code properly. | |
// For example: ReactDOM.unmountComponentAtNode(this.element); | |
disconnect() { | |
[...this.element.children].map(el => this.removeScript(el)); | |
} | |
removeScript(element) { | |
if (element.nodeName == 'SCRIPT') { | |
element.parentElement?.removeChild(element); | |
} | |
} | |
activateScript(element) { | |
if (element.nodeName == 'SCRIPT') { | |
const createdScriptElement = document.createElement("script"); | |
createdScriptElement.textContent = element.textContent; | |
createdScriptElement.async = false; | |
this.copyElementAttributes(createdScriptElement, element); | |
this.replaceElementWithElement(element, createdScriptElement); | |
} | |
} | |
replaceElementWithElement(fromElement, toElement) { | |
const parentElement = fromElement.parentElement | |
if (parentElement) { | |
return parentElement.replaceChild(toElement, fromElement) | |
} | |
} | |
copyElementAttributes(destinationElement, sourceElement) { | |
for (const { name, value } of [ ...sourceElement.attributes ]) { | |
destinationElement.setAttribute(name, value) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I have updated the gist to apply a workaround for a bug that was mentioned in: hotwired/turbo#225
The script is loaded twice:
This change removes the script elements just before the cache is stored so on restore they are not there anymore preventing the bug to trigger.
Normally you would check if the preview is visible by using: https://turbo.hotwire.dev/handbook/building#detecting-when-a-preview-is-visible and not execute the
activateScript
method.But that is currently not available.
By all means, this gist is not perfect. But it helps bridging the time before the fix is merged into Turbo itself.