Use <template> to Restore DOM State
by Julian Rubisch
Pain Point
- You’re dealing with an external library that yanks HTML off your page and you need to restore it.
- You want to restore the page to a known state before leaving, e.g. to prepare for Turbo caching.
Good
<!– index.html –>
<div data-controller=“modal”>
<template data-modal-target=“template”>
<div>
<a href=“#” data-action=“modal#show”>Click Me</a>
<div class=“modal invisible” data-modal-target=“modal”>
<h1>A Modal</h1>
<a href=“#” data-action=“modal#hide”>Hide Me</a>
</div>
</div>
</template>
</div>
<!-- index.html --> <div data-controller="modal"> <template data-modal-target="template"> <div> <a href="#" data-action="modal#show">Click Me</a> <div class="modal invisible" data-modal-target="modal"> <h1>A Modal</h1> <a href="#" data-action="modal#hide">Hide Me</a> </div> </div> </template> </div>
// modal_controller.js
import { Controller } from “@hotwired/stimulus”;
export default class extends Controller {
static targets = [“template”, “modal”];
connect() {
this.element.insertAdjacentHTML(“beforeend”, this.templateTarget.innerHTML);
}
show(e) {
e.preventDefault();
// this is a stand-in for an external show method, e.g. in Bootstrap or SemanticUI
this.modalTarget.classList.remove(“invisible”);
this.modalTarget.classList.add(“visible”);
}
hide(e) {
e.preventDefault();
// this is a stand-in for an external hide method that will
// yank the modal HTML off your page
this.element.removeChild(this.element.lastElementChild);
this.element.insertAdjacentHTML(“beforeend”, this.templateTarget.innerHTML);
}
}
// modal_controller.js import { Controller } from "@hotwired/stimulus"; export default class extends Controller { static targets = ["template", "modal"]; connect() { this.element.insertAdjacentHTML("beforeend", this.templateTarget.innerHTML); } show(e) { e.preventDefault(); // this is a stand-in for an external show method, e.g. in Bootstrap or SemanticUI this.modalTarget.classList.remove("invisible"); this.modalTarget.classList.add("visible"); } hide(e) { e.preventDefault(); // this is a stand-in for an external hide method that will // yank the modal HTML off your page this.element.removeChild(this.element.lastElementChild); this.element.insertAdjacentHTML("beforeend", this.templateTarget.innerHTML); } }
Rationale
In some cases, it can be necessary to reset your DOM to a known state before leaving the page, or after triggering some action. One use case might be when dealing with external UI libraries like SemanticUI or Bootstrap that will yank away some HTML after, for example, closing a modal.
Furthermore this can be useful when using Turbo, because it will cache the current state before navigating away and show it as a preview when doing a restoration visit.
Contraindications
Certainly there are easier ways to restore markup when manipulating the DOM, especially when you’re dealing only with single elements on which you toggle CSS classes. Whenever you need to replace larger portions of HTML, this can be a viable option, though.