Created
February 26, 2021 13:48
-
-
Save boardfish/2b55f511fbb463ac270419b00a202680 to your computer and use it in GitHub Desktop.
Controller for lazy-loading multiple Turbo frames from the same request
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" | |
// Use this if you'd like to lazy-load multiple Turbo Frames from the same | |
// request. Make sure that your controller responds with a Turbo Stream, then | |
// add a div to your view like this: | |
// <div data-controller="lazy-load" data-lazy-load-path-value="<%= my_activities_path %>"></div> | |
// Then, when the page loads, the browser will send a GET request to the path | |
// you've set for data-lazy-load-path-value, and add the response to the DOM. | |
// If you only need to lazy-load one Turbo frame on the page, use the src | |
// attribute and HTML responses instead. | |
export default class extends Controller { | |
static values = { path: String } | |
connect() { | |
// Send a request asking for a Turbo Stream response | |
fetch(this.pathValue, { | |
headers: { | |
Accept: "text/html; turbo-stream, text/html, application/xhtml+xml", | |
}, | |
}) | |
// Convert the response body to text.. | |
.then((response) => response.text()) | |
// ...then create HTML elements from that, and append them to this | |
// element. Turbo Streams are evaluated as they're added to the DOM. Where | |
// they're appended doesn't matter, because they'll only change the Turbo | |
// Frame they're marked for. | |
.then((body) => | |
this.htmlToElements(body).forEach((element) => | |
this.element.appendChild(element) | |
) | |
) | |
} | |
/** | |
* https://stackoverflow.com/a/35385518 | |
* @param {String} HTML representing any number of sibling elements | |
* @return {NodeList} | |
*/ | |
htmlToElements(html) { | |
var template = document.createElement("template") | |
template.innerHTML = html.trim() | |
return template.content.childNodes | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment